BVB Source Codes

CRYENGINE Show AIPlayer.cpp Source code

Return Download CRYENGINE: download AIPlayer.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /********************************************************************
  4.    -------------------------------------------------------------------------
  5.    File name:   AIPlayer.cpp
  6.    $Id$
  7.    Description:
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    - ?
  12.  
  13.  *********************************************************************/
  14.  
  15. #include "StdAfx.h"
  16. #include "AIPlayer.h"
  17. #include "CAISystem.h"
  18. #include "DebugDrawContext.h"
  19. #include "MissLocationSensor.h"
  20. #include "Puppet.h"
  21.  
  22. #include <CryAISystem/VisionMapTypes.h>
  23.  
  24. // The variables needs to be carefully tuned to possible the player action speeds.
  25. static const float PLAYER_ACTION_SPRINT_RESET_TIME = 0.5f;
  26. static const float PLAYER_ACTION_JUMP_RESET_TIME = 1.3f;
  27. static const float PLAYER_ACTION_CLOAK_RESET_TIME = 1.5f;
  28.  
  29. static const float PLAYER_IGNORE_COVER_TIME = 6.0f;
  30.  
  31. //
  32. //---------------------------------------------------------------------------------
  33. CAIPlayer::CAIPlayer()
  34.         : m_lastGrabbedEntityID(0)
  35.         , m_FOV(0)
  36.         , m_damagePartsUpdated(false)
  37.         , m_deathCount(0)
  38.         , m_stuntDir(ZERO)
  39.         , m_playerStuntSprinting(-1.0f)
  40.         , m_playerStuntJumping(-1.0f)
  41.         , m_playerStuntCloaking(-1.0f)
  42.         , m_playerStuntUncloaking(-1.0f)
  43.         , m_mercyTimer(-1.0f)
  44.         , m_coverExposedTime(-1.0f)
  45.         , m_coolMissCooldown(0.0f)
  46. #pragma warning(disable: 4355)
  47. #if ENABLE_MISSLOCATION_SENSOR
  48.         , m_pMissLocationSensor(new CMissLocationSensor(this))
  49. #endif
  50. {
  51.         _fastcast_CAIPlayer = true;
  52. }
  53.  
  54. //
  55. //---------------------------------------------------------------------------------
  56. CAIPlayer::~CAIPlayer()
  57. {
  58.         if (m_exposedCoverState.rayID)
  59.                 gAIEnv.pRayCaster->Cancel(m_exposedCoverState.rayID);
  60.  
  61.         ReleaseExposedCoverObjects();
  62. }
  63.  
  64. //
  65. //---------------------------------------------------------------------------------
  66. void CAIPlayer::Reset(EObjectResetType type)
  67. {
  68.         MyBase::Reset(type);
  69.  
  70.         SetObservable(type == AIOBJRESET_INIT);
  71.  
  72.         m_fLastUpdateTargetTime = 0.f;
  73.         m_lastGrabbedEntityID = 0;
  74.  
  75.         if (m_exposedCoverState.rayID)
  76.         {
  77.                 gAIEnv.pRayCaster->Cancel(m_exposedCoverState.rayID);
  78.                 m_exposedCoverState.rayID = 0;
  79.         }
  80.  
  81.         m_deathCount = 0;
  82.         m_lastThrownItems.clear();
  83.         m_stuntTargets.clear();
  84.         m_stuntDir.Set(0, 0, 0);
  85.         m_mercyTimer = -1.0f;
  86.         m_coverExposedTime = -1.0f;
  87.         m_coolMissCooldown = 0.0f;
  88.         m_damagePartsUpdated = false;
  89.  
  90. #if ENABLE_MISSLOCATION_SENSOR
  91.         if (m_pMissLocationSensor.get())
  92.                 m_pMissLocationSensor->Reset();
  93. #endif
  94.  
  95.         ReleaseExposedCoverObjects();
  96. }
  97.  
  98. //
  99. //---------------------------------------------------------------------------------
  100. void CAIPlayer::ReleaseExposedCoverObjects()
  101. {
  102.         for (unsigned i = 0, ni = m_exposedCoverObjects.size(); i < ni; ++i)
  103.                 m_exposedCoverObjects[i].pPhysEnt->Release();
  104.         m_exposedCoverObjects.clear();
  105. }
  106.  
  107. //
  108. //---------------------------------------------------------------------------------
  109. void CAIPlayer::AddExposedCoverObject(IPhysicalEntity* pPhysEnt)
  110. {
  111.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  112.  
  113.         unsigned oldest = 0;
  114.         float oldestTime = FLT_MAX; // Count down timers, find smallest value.
  115.         for (unsigned i = 0, ni = m_exposedCoverObjects.size(); i < ni; ++i)
  116.         {
  117.                 SExposedCoverObject& co = m_exposedCoverObjects[i];
  118.                 if (co.pPhysEnt == pPhysEnt)
  119.                 {
  120.                         co.t = PLAYER_IGNORE_COVER_TIME;
  121.                         return;
  122.                 }
  123.                 if (co.t < oldestTime)
  124.                 {
  125.                         oldest = i;
  126.                         oldestTime = co.t;
  127.                 }
  128.         }
  129.  
  130.         // Limit the number of covers, override oldest one.
  131.         if (m_exposedCoverObjects.size() >= 3)
  132.         {
  133.                 // Release the previous entity
  134.                 m_exposedCoverObjects[oldest].pPhysEnt->Release();
  135.                 // Fill in new.
  136.                 pPhysEnt->AddRef();
  137.                 m_exposedCoverObjects[oldest].pPhysEnt = pPhysEnt;
  138.                 m_exposedCoverObjects[oldest].t = PLAYER_IGNORE_COVER_TIME;
  139.         }
  140.         else
  141.         {
  142.                 // Add new
  143.                 pPhysEnt->AddRef();
  144.                 m_exposedCoverObjects.push_back(SExposedCoverObject(pPhysEnt, PLAYER_IGNORE_COVER_TIME));
  145.         }
  146. }
  147.  
  148. //
  149. //---------------------------------------------------------------------------------
  150. void CAIPlayer::CollectExposedCover()
  151. {
  152.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  153.  
  154.         if (m_coverExposedTime > 0.0f)
  155.         {
  156.                 if (m_exposedCoverState.asyncState == AsyncReady)
  157.                 {
  158.                         m_exposedCoverState.asyncState = AsyncInProgress;
  159.  
  160.                         // Find the object directly in front of the player
  161.                         const Vec3& pos = GetPos();
  162.                         const Vec3 dir = GetViewDir() * 3.0f;
  163.                         const int flags = rwi_colltype_any | (geom_colltype_obstruct << rwi_colltype_bit) | (AI_VISION_RAY_CAST_PIERCEABILITY & rwi_pierceability_mask);
  164.  
  165.                         m_exposedCoverState.rayID = gAIEnv.pRayCaster->Queue(
  166.                           RayCastRequest::MediumPriority,
  167.                           RayCastRequest(pos, dir, ent_static, flags),
  168.                           functor(*this, &CAIPlayer::CollectExposedCoverRayComplete));
  169.                 }
  170.         }
  171. }
  172.  
  173. void CAIPlayer::CollectExposedCoverRayComplete(const QueuedRayID& rayID, const RayCastResult& result)
  174. {
  175.         if (m_exposedCoverState.rayID == rayID)
  176.         {
  177.                 m_exposedCoverState.rayID = 0;
  178.                 m_exposedCoverState.asyncState = AsyncReady;
  179.  
  180.                 if (result && result[0].pCollider)
  181.                         AddExposedCoverObject(result[0].pCollider);
  182.         }
  183. }
  184.  
  185. void CAIPlayer::GetObservablePositions(ObservableParams& observableParams) const
  186. {
  187.         IEntity* entity = GetEntity();
  188.         IF_UNLIKELY (!entity)
  189.         {
  190.                 return;
  191.         }
  192.  
  193.         const Vec3& pos = GetPos();
  194.         const Quat& rotation = entity->GetRotation();
  195.  
  196.         observableParams.observablePositionsCount = 3;
  197.         observableParams.observablePositions[0] = pos;
  198.  
  199.         // shoulder positions
  200.         observableParams.observablePositions[1] = pos + (rotation * Vec3(0.15f, 0.0f, -0.2f));
  201.         observableParams.observablePositions[2] = pos + (rotation * Vec3(-0.15f, 0.0f, -0.2f));
  202. }
  203.  
  204. uint32 CAIPlayer::GetObservableTypeMask() const
  205. {
  206.         return MyBase::GetObservableTypeMask() | Player;
  207. }
  208.  
  209. //
  210. //---------------------------------------------------------------------------------
  211. void CAIPlayer::GetPhysicalSkipEntities(PhysSkipList& skipList) const
  212. {
  213.         MyBase::GetPhysicalSkipEntities(skipList);
  214.  
  215.         // Skip exposed covers
  216.         for (uint32 i = 0, ni = m_exposedCoverObjects.size(); i < ni; ++i)
  217.         {
  218.                 stl::push_back_unique(skipList, m_exposedCoverObjects[i].pPhysEnt);
  219.         }
  220.  
  221.         CRY_ASSERT_MESSAGE(skipList.size() <= 5, "Too many physical skipped entities determined. See SRwiRequest definition.");
  222. }
  223.  
  224. //
  225. //---------------------------------------------------------------------------------
  226. void CAIPlayer::ParseParameters(const AIObjectParams& params, bool bParseMovementParams)
  227. {
  228.         MyBase::ParseParameters(params, bParseMovementParams);
  229.         m_Parameters = params.m_sParamStruct;
  230. }
  231.  
  232. //
  233. //---------------------------------------------------------------------------------
  234. IAIObject::EFieldOfViewResult CAIPlayer::IsPointInFOV(const Vec3& pos, float distanceScale) const
  235. {
  236.         EFieldOfViewResult eResult = eFOV_Outside;
  237.  
  238.         Vec3 vDirection = pos - GetPos();
  239.         const float fDirectionLengthSq = vDirection.GetLengthSquared();
  240.         vDirection.NormalizeSafe();
  241.  
  242.         // lets see if it is outside of its vision range
  243.         if (fDirectionLengthSq > 0.1f && fDirectionLengthSq <= sqr(m_Parameters.m_PerceptionParams.sightRange * distanceScale))
  244.         {
  245.                 const Vec3 vViewDir = GetViewDir().GetNormalizedSafe();
  246.                 const float fDot = vDirection.Dot(vViewDir);
  247.  
  248.                 eResult = (fDot >= m_FOV ? eFOV_Primary : eFOV_Outside);
  249.         }
  250.  
  251.         return eResult;
  252. }
  253.  
  254. //
  255. //---------------------------------------------------------------------------------
  256. void CAIPlayer::UpdateAttentionTarget(CWeakRef<CAIObject> refTarget)
  257. {
  258.         bool bSameTarget = (m_refAttentionTarget == refTarget);
  259.         if (bSameTarget)
  260.         {
  261.                 m_fLastUpdateTargetTime = GetAISystem()->GetFrameStartTime();
  262.         }
  263.         else // compare the new target with the current one
  264.         {
  265.                 CCCPOINT(CAIPlayer_UpdateAttentionTarget);
  266.  
  267.                 CAIObject* pAttentionTarget = m_refAttentionTarget.GetAIObject();
  268.                 CAIObject* pTarget = refTarget.GetAIObject();
  269.  
  270.                 Vec3 direction = pAttentionTarget->GetPos() - GetPos();
  271.  
  272.                 // lets see if it is outside of its vision range
  273.  
  274.                 Vec3 myorievector = GetViewDir();
  275.                 float dist = direction.GetLength();
  276.  
  277.                 if (dist > 0)
  278.                         direction /= dist;
  279.                 Vec3 directionNew(pTarget->GetPos() - GetPos());
  280.  
  281.                 float distNew = directionNew.GetLength();
  282.                 if (distNew > 0)
  283.                         directionNew /= dist;
  284.  
  285.                 float fdot = ((Vec3)direction).Dot((Vec3)myorievector);
  286.                 // check if new target is more interesting, by checking if old target is still visible
  287.                 // and comparing distances if it is
  288.                 if (fdot < 0 || fdot < m_FOV || distNew < dist)
  289.                 {
  290.                         m_refAttentionTarget = refTarget;
  291.                         m_fLastUpdateTargetTime = GetAISystem()->GetFrameStartTime();
  292.                 }
  293.         }
  294. }
  295.  
  296. //
  297. //---------------------------------------------------------------------------------
  298. float CAIPlayer::AdjustTargetVisibleRange(const CAIActor& observer, float fVisibleRange) const
  299. {
  300.         float fRangeScale = 1.0f;
  301.  
  302.         // Adjust using my light level if the observer is affected by light
  303.         if (IsAffectedByLight())
  304.         {
  305.                 const EAILightLevel targetLightLevel = GetLightLevel();
  306.                 switch (targetLightLevel)
  307.                 {
  308.                 //      case AILL_LIGHT: SOMSpeed
  309.                 case AILL_MEDIUM:
  310.                         fRangeScale *= gAIEnv.CVars.SightRangeMediumIllumMod;
  311.                         break;
  312.                 case AILL_DARK:
  313.                         fRangeScale *= gAIEnv.CVars.SightRangeDarkIllumMod;
  314.                         break;
  315.                 case AILL_SUPERDARK:
  316.                         fRangeScale *= gAIEnv.CVars.SightRangeSuperDarkIllumMod;
  317.                         break;
  318.                 }
  319.         }
  320.  
  321.         // Scale down sight range when target is underwater based on distance
  322.         const float fCachedWaterOcclusionValue = GetCachedWaterOcclusionValue();
  323.         if (fCachedWaterOcclusionValue > FLT_EPSILON)
  324.         {
  325.                 const Vec3& observerPos = observer.GetPos();
  326.                 const float fDistance = Distance::Point_Point(GetPos(), observerPos);
  327.                 const float fDistanceFactor = (fVisibleRange > FLT_EPSILON ? GetAISystem()->GetVisPerceptionDistScale(fDistance / fVisibleRange) : 0.0f);
  328.  
  329.                 const float fWaterOcclusionEffect = 2.0f * fCachedWaterOcclusionValue + (1 - fDistanceFactor) * 0.5f;
  330.  
  331.                 fRangeScale *= (fWaterOcclusionEffect > 1.0f ? 0.0f : 1.0f - fWaterOcclusionEffect);
  332.         }
  333.  
  334.         // Return new range
  335.         return fVisibleRange * fRangeScale;
  336. }
  337.  
  338. //
  339. //---------------------------------------------------------------------------------
  340. bool CAIPlayer::IsAffectedByLight() const
  341. {
  342.         return (gAIEnv.CVars.PlayerAffectedByLight != 0 ||
  343.                 MyBase::IsAffectedByLight());
  344. }
  345.  
  346. //
  347. //---------------------------------------------------------------------------------
  348. void CAIPlayer::Update(EObjectUpdate type)
  349. {
  350.         if (m_refAttentionTarget.IsValid())
  351.         {
  352.                 if (!m_refAttentionTarget.GetAIObject()->IsEnabled() ||
  353.                     (GetAISystem()->GetFrameStartTime() - m_fLastUpdateTargetTime).GetMilliSecondsAsInt64() > 5000)
  354.                         m_refAttentionTarget.Reset();
  355.         }
  356.  
  357.         // There should never be player without physics (except in multiplayer, this case is valid).
  358.         if (!GetPhysics())
  359.         {
  360.                 if (!gEnv->bMultiplayer)
  361.                 {
  362.                         AIWarning("AIPlayer::Update Player %s does not have physics!", GetName());
  363.                 }
  364.                 return;
  365.         }
  366.  
  367. #if ENABLE_MISSLOCATION_SENSOR
  368.         if (m_pMissLocationSensor.get())
  369.                 m_pMissLocationSensor->DebugDraw();
  370. #endif
  371.  
  372.         CCCPOINT(CAIPlayer_Update);
  373.  
  374.         IEntity* grabbedEntity = GetGrabbedEntity();
  375.         EntityId grabbedEntityID = grabbedEntity ? grabbedEntity->GetId() : 0;
  376.  
  377.         if (m_lastGrabbedEntityID != grabbedEntityID)
  378.         {
  379.                 UpdateObservableSkipList();
  380.  
  381.                 m_lastGrabbedEntityID = grabbedEntityID;
  382.         }
  383.  
  384.         // make sure to update direction when entity is not moved
  385.         const SAIBodyInfo& bodyInfo = QueryBodyInfo();
  386.         SetPos(bodyInfo.vEyePos);
  387.         SetEntityDir(bodyInfo.vEntityDir);
  388.         SetMoveDir(bodyInfo.vMoveDir);
  389.         SetViewDir(bodyInfo.GetEyeDir());
  390.         SetBodyDir(bodyInfo.GetBodyDir());
  391.  
  392.         // Determine if position has changed. When crouching/standing we also need to recalculate the water
  393.         // occlusion value even if we didn't move at least one meter.
  394.         const float zMinDifferenceBetweenStandAndCrouchToRecalculateWaterOcclusion = 0.6f;
  395.         const bool playerFullyChangedStance = (m_lastFullUpdateStance != bodyInfo.stance)
  396.                                               && abs(m_vLastFullUpdatePos.z - bodyInfo.vEyePos.z) > zMinDifferenceBetweenStandAndCrouchToRecalculateWaterOcclusion;
  397.         if (type == AIUPDATE_FULL && (!IsEquivalent(m_vLastFullUpdatePos, bodyInfo.vEyePos, 1.0f) || playerFullyChangedStance))
  398.         {
  399.                 // Recalculate the water occlusion at the new point
  400.                 m_cachedWaterOcclusionValue = GetAISystem()->GetWaterOcclusionValue(bodyInfo.vEyePos);
  401.  
  402.                 m_vLastFullUpdatePos = bodyInfo.vEyePos;
  403.                 m_lastFullUpdateStance = bodyInfo.stance;
  404.         }
  405.  
  406.         m_bUpdatedOnce = true;
  407.  
  408.         //@TODO: It is wrong here to use Global Camera!
  409.         m_FOV = cosf(GetISystem()->GetViewCamera().GetFov());
  410.  
  411.         if (IsObserver())
  412.                 VisionChanged(75.0f, m_FOV, m_FOV);
  413.  
  414.         // (MATT) I'm assuming that AIActor should always have a proxy, or this could be bad for performance {2009/04/03}
  415.         IAIActorProxy* pProxy = GetProxy();
  416.         if (pProxy)
  417.                 pProxy->UpdateMind(m_State);
  418.  
  419.         if (type == AIUPDATE_FULL)
  420.         {
  421.                 m_lightLevel = GetAISystem()->GetLightManager()->GetLightLevelAt(GetPos(), this, &m_usingCombatLight);
  422.  
  423. #if ENABLE_MISSLOCATION_SENSOR
  424.                 m_pMissLocationSensor->Update(0.005f);
  425. #endif
  426.  
  427. #ifdef CRYAISYSTEM_DEBUG
  428.                 // Health
  429.                 {
  430.                         RecorderEventData recorderEventData(GetProxy()->GetActorHealth());
  431.                         RecordEvent(IAIRecordable::E_HEALTH, &recorderEventData);
  432.                 }
  433.  
  434.                 // Pos
  435.                 {
  436.                         RecorderEventData recorderEventData(GetPos());
  437.                         RecordEvent(IAIRecordable::E_AGENTPOS, &recorderEventData);
  438.                 }
  439.  
  440.                 // Dir
  441.                 {
  442.                         RecorderEventData recorderEventData(GetViewDir());
  443.                         RecordEvent(IAIRecordable::E_AGENTDIR, &recorderEventData);
  444.                 }
  445. #endif  // #ifdef CRYAISYSTEM_DEBUG
  446.         }
  447.  
  448.         const float dt = GetAISystem()->GetFrameDeltaTime();
  449.  
  450.         if (m_coolMissCooldown > 0.0f)
  451.                 m_coolMissCooldown -= dt;
  452.  
  453.         // Exposed (soft) covers. When the player fires the weapon,
  454.         // disable the cover where the player is hiding at or the
  455.         // soft cover the player is shooting at.
  456.  
  457.         // Timeout the cover exposure timer.
  458.         if (m_coverExposedTime > 0.0f)
  459.                 m_coverExposedTime -= dt;
  460.         else
  461.                 m_coverExposedTime = -1.0f;
  462.  
  463.         if (GetProxy())
  464.         {
  465.                 SAIWeaponInfo wi;
  466.                 GetProxy()->QueryWeaponInfo(wi);
  467.                 if (wi.isFiring)
  468.                         m_coverExposedTime = 1.0f;
  469.         }
  470.  
  471.         // Timeout the exposed covers
  472.         for (unsigned i = 0; i < m_exposedCoverObjects.size(); )
  473.         {
  474.                 m_exposedCoverObjects[i].t -= dt;
  475.                 if (m_exposedCoverObjects[i].t < 0.0f)
  476.                 {
  477.                         m_exposedCoverObjects[i].pPhysEnt->Release();
  478.                         m_exposedCoverObjects[i] = m_exposedCoverObjects.back();
  479.                         m_exposedCoverObjects.pop_back();
  480.                 }
  481.                 else
  482.                         ++i;
  483.         }
  484.  
  485.         // Collect new covers.
  486.         if (type == AIUPDATE_FULL)
  487.                 CollectExposedCover();
  488.  
  489. #ifdef CRYAISYSTEM_DEBUG
  490.         if (gAIEnv.CVars.DebugDrawDamageControl > 0)
  491.                 UpdateHealthHistory();
  492. #endif
  493.  
  494.         UpdatePlayerStuntActions();
  495.         UpdateCloakScale();
  496.  
  497.         // Update low health mercy pause
  498.         if (m_mercyTimer > 0.0f)
  499.                 m_mercyTimer -= GetAISystem()->GetFrameDeltaTime();
  500.         else
  501.                 m_mercyTimer = -1.0f;
  502.  
  503.         m_damagePartsUpdated = false;
  504. }
  505.  
  506. void CAIPlayer::OnObjectRemoved(CAIObject* pObject)
  507. {
  508.         MyBase::OnObjectRemoved(pObject);
  509.  
  510.         // (MATT) Moved here from CAISystems call {2009/02/05}
  511.         CAIActor* pRemovedAIActor = pObject->CastToCPuppet();
  512.         if (!pRemovedAIActor)
  513.                 return;
  514.  
  515.         for (unsigned i = 0; i < m_stuntTargets.size(); )
  516.         {
  517.                 if (m_stuntTargets[i].pAIActor == pRemovedAIActor)
  518.                 {
  519.                         m_stuntTargets[i] = m_stuntTargets.back();
  520.                         m_stuntTargets.pop_back();
  521.                 }
  522.                 else
  523.                         ++i;
  524.         }
  525. }
  526.  
  527. void CAIPlayer::UpdatePlayerStuntActions()
  528. {
  529.         ActorLookUp& lookUp = *gAIEnv.pActorLookUp;
  530.         lookUp.Prepare(ActorLookUp::Position);
  531.  
  532.         const float dt = GetAISystem()->GetFrameDeltaTime();
  533.  
  534.         // Update thrown entities
  535.         for (unsigned i = 0; i < m_lastThrownItems.size(); )
  536.         {
  537.                 IEntity* pEnt = gEnv->pEntitySystem->GetEntity(m_lastThrownItems[i].id);
  538.                 if (pEnt)
  539.                 {
  540.                         if (IPhysicalEntity* pPhysEnt = pEnt->GetPhysics())
  541.                         {
  542.                                 pe_status_dynamics statDyn;
  543.                                 pPhysEnt->GetStatus(&statDyn);
  544.                                 m_lastThrownItems[i].pos = pEnt->GetWorldPos();
  545.                                 m_lastThrownItems[i].vel = statDyn.v;
  546.                                 if (statDyn.v.GetLengthSquared() > sqr(3.0f))
  547.                                         m_lastThrownItems[i].time = 0;
  548.                         }
  549.                 }
  550.  
  551.                 m_lastThrownItems[i].time += dt;
  552.                 if (!pEnt || m_lastThrownItems[i].time > 1.0f)
  553.                 {
  554.                         m_lastThrownItems[i] = m_lastThrownItems.back();
  555.                         m_lastThrownItems.pop_back();
  556.                 }
  557.                 else
  558.                         ++i;
  559.         }
  560.  
  561.         Vec3 vel = GetVelocity();
  562.         float speed = vel.GetLength();
  563.  
  564.         m_stuntDir = vel;
  565.         if (m_stuntDir.GetLength() < 0.001f)
  566.                 m_stuntDir = GetEntityDir();
  567.         m_stuntDir.z = 0;
  568.         m_stuntDir.NormalizeSafe();
  569.  
  570.         if (m_playerStuntSprinting > 0.0f)
  571.         {
  572.                 if (speed > 10.0f)
  573.                         m_playerStuntSprinting = PLAYER_ACTION_SPRINT_RESET_TIME;
  574.                 m_playerStuntSprinting -= dt;
  575.         }
  576.  
  577.         if (m_playerStuntJumping > 0.0f)
  578.         {
  579.                 if (speed > 7.0f)
  580.                         m_playerStuntJumping = PLAYER_ACTION_JUMP_RESET_TIME;
  581.                 m_playerStuntJumping -= dt;
  582.         }
  583.  
  584.         if (m_playerStuntCloaking > 0.0f)
  585.                 m_playerStuntCloaking -= dt;
  586.  
  587.         if (m_playerStuntUncloaking > 0.0f)
  588.                 m_playerStuntUncloaking -= dt;
  589.  
  590.         bool checkMovement = m_playerStuntSprinting > 0.0f || m_playerStuntJumping > 0.0f;
  591.         bool checkItems = !m_lastThrownItems.empty();
  592.  
  593.         if (checkMovement || checkItems)
  594.         {
  595.                 float movementScale = 0.7f;
  596.                 //              if (m_playerStuntJumping > 0.0f)
  597.                 //                      movementScale *= 2.0f;
  598.  
  599.                 Lineseg playerMovement(GetPos(), GetPos() + vel * movementScale);
  600.                 const SAIBodyInfo& bi = GetBodyInfo();
  601.                 float playerRad = bi.stanceSize.GetRadius();
  602.  
  603.                 // Update stunt effect on AI actors
  604.                 size_t activeCount = lookUp.GetActiveCount();
  605.  
  606.                 for (size_t actorIndex = 0; actorIndex < activeCount; ++actorIndex)
  607.                 {
  608.                         CAIActor* pAIActor = lookUp.GetActor<CAIActor>(actorIndex);
  609.  
  610.                         if (!IsHostile(pAIActor))
  611.                                 continue;
  612.  
  613.                         const float scale = pAIActor->GetParameters().m_PerceptionParams.collisionReactionScale;
  614.  
  615.                         bool hit = false;
  616.  
  617.                         float t, distSq;
  618.                         Vec3 threatPos;
  619.  
  620.                         if (checkMovement)
  621.                         {
  622.                                 // Player movement
  623.                                 distSq = Distance::Point_Lineseg2DSq(lookUp.GetPosition(actorIndex), playerMovement, t);
  624.                                 if (distSq < sqr(playerRad * scale))
  625.                                 {
  626.                                         threatPos = GetPos();
  627.                                         hit = true;
  628.                                 }
  629.                         }
  630.  
  631.                         if (checkItems)
  632.                         {
  633.                                 // Thrown items
  634.                                 for (unsigned i = 0, ni = m_lastThrownItems.size(); i < ni; ++i)
  635.                                 {
  636.                                         Lineseg itemMovement(m_lastThrownItems[i].pos, m_lastThrownItems[i].pos + m_lastThrownItems[i].vel * 2);
  637.                                         distSq = Distance::Point_LinesegSq(lookUp.GetPosition(actorIndex), itemMovement, t);
  638.                                         if (distSq < sqr(m_lastThrownItems[i].r * 2.0f * scale))
  639.                                         {
  640.                                                 threatPos = m_lastThrownItems[i].pos;
  641.                                                 hit = true;
  642.                                         }
  643.                                 }
  644.                         }
  645.  
  646.                         if (hit)
  647.                         {
  648.                                 bool found = false;
  649.                                 for (unsigned i = 0, ni = m_stuntTargets.size(); i < ni; ++i)
  650.                                 {
  651.                                         if (m_stuntTargets[i].pAIActor == pAIActor)
  652.                                         {
  653.                                                 m_stuntTargets[i].threatPos = threatPos;
  654.                                                 m_stuntTargets[i].exposed += dt;
  655.                                                 m_stuntTargets[i].t = 0;
  656.                                                 found = true;
  657.                                                 break;
  658.                                         }
  659.                                 }
  660.                                 if (!found)
  661.                                 {
  662.                                         m_stuntTargets.push_back(SStuntTargetAIActor(pAIActor, threatPos));
  663.                                         m_stuntTargets.back().exposed += dt;
  664.                                 }
  665.                         }
  666.                 }
  667.         }
  668.  
  669.         for (unsigned i = 0; i < m_stuntTargets.size(); )
  670.         {
  671.                 m_stuntTargets[i].t += dt;
  672.                 CAIActor* pAIActor = m_stuntTargets[i].pAIActor;
  673.                 if (!m_stuntTargets[i].signalled
  674.                     && m_stuntTargets[i].exposed > 0.15f
  675.                     && pAIActor->GetAttentionTarget()
  676.                     && pAIActor->GetAttentionTarget()->GetEntityID() == GetEntityID())
  677.                 {
  678.                         IAISignalExtraData* pData = GetAISystem()->CreateSignalExtraData();
  679.                         pData->iValue = 1;
  680.                         pData->fValue = Distance::Point_Point(m_stuntTargets[i].pAIActor->GetPos(), m_stuntTargets[i].threatPos);
  681.                         pData->point = m_stuntTargets[i].threatPos;
  682.                         pAIActor->SetSignal(1, "OnCloseCollision", 0, pData);
  683.                         if (CPuppet* pPuppet = pAIActor->CastToCPuppet())
  684.                                 pPuppet->SetAlarmed();
  685.                         m_stuntTargets[i].signalled = true;
  686.                 }
  687.                 if (m_stuntTargets[i].t > 2.0f)
  688.                 {
  689.                         m_stuntTargets[i] = m_stuntTargets.back();
  690.                         m_stuntTargets.pop_back();
  691.                 }
  692.                 else
  693.                         ++i;
  694.         }
  695. }
  696.  
  697. bool CAIPlayer::IsDoingStuntActionRelatedTo(const Vec3& pos, float nearDistance)
  698. {
  699.         if (m_playerStuntCloaking > 0.0f)
  700.                 return true;
  701.  
  702.         if (m_playerStuntSprinting <= 0.0f && m_playerStuntJumping <= 0.0f)
  703.                 return false;
  704.  
  705.         // If the stunt is not done at really close range,
  706.         // do not consider the stunt unless it is towards the specified position.
  707.         Vec3 diff = pos - GetPos();
  708.         diff.z = 0;
  709.         float dist = diff.NormalizeSafe();
  710.         const float thr = cosf(DEG2RAD(75.0f));
  711.         if (dist > nearDistance && m_stuntDir.Dot(diff) < thr)
  712.                 return false;
  713.  
  714.         return true;
  715. }
  716.  
  717. bool CAIPlayer::IsThrownByPlayer(EntityId id) const
  718. {
  719.         if (m_lastThrownItems.empty()) return false;
  720.         for (unsigned i = 0, ni = m_lastThrownItems.size(); i < ni; ++i)
  721.                 if (m_lastThrownItems[i].id == id)
  722.                         return true;
  723.         return false;
  724. }
  725.  
  726. bool CAIPlayer::IsPlayerStuntAffectingTheDeathOf(CAIActor* pDeadActor) const
  727. {
  728.         if (!pDeadActor || !pDeadActor->GetEntity())
  729.                 return false;
  730.  
  731.         // If the actor is thrown/punched by the player.
  732.         if (IsThrownByPlayer(pDeadActor->GetEntityID()))
  733.                 return true;
  734.  
  735.         // If any of the objects the player has thrown is close to the dead body.
  736.         AABB deadBounds;
  737.         pDeadActor->GetEntity()->GetWorldBounds(deadBounds);
  738.         Vec3 deadPos = deadBounds.GetCenter();
  739.         float deadRadius = deadBounds.GetRadius();
  740.  
  741.         for (unsigned i = 0, ni = m_lastThrownItems.size(); i < ni; ++i)
  742.         {
  743.                 if (Distance::Point_PointSq(deadPos, m_lastThrownItems[i].pos) < sqr(deadRadius + m_lastThrownItems[i].r))
  744.                         return true;
  745.         }
  746.  
  747.         return false;
  748. }
  749.  
  750. EntityId CAIPlayer::GetNearestThrownEntity(const Vec3& pos)
  751. {
  752.         EntityId nearest = 0;
  753.         float nearestDist = FLT_MAX;
  754.         for (unsigned i = 0, ni = m_lastThrownItems.size(); i < ni; ++i)
  755.         {
  756.                 float d = Distance::Point_Point(pos, m_lastThrownItems[i].pos) - m_lastThrownItems[i].r;
  757.                 if (d < nearestDist)
  758.                 {
  759.                         nearestDist = d;
  760.                         nearest = m_lastThrownItems[i].id;
  761.                 }
  762.         }
  763.         return nearest;
  764. }
  765.  
  766. void CAIPlayer::AddThrownEntity(EntityId id)
  767. {
  768.         float oldestTime = 0.0f;
  769.         unsigned oldestId = 0;
  770.         for (unsigned i = 0, ni = m_lastThrownItems.size(); i < ni; ++i)
  771.         {
  772.                 if (m_lastThrownItems[i].id == id)
  773.                 {
  774.                         m_lastThrownItems[i].time = 0;
  775.                         return;
  776.                 }
  777.                 if (m_lastThrownItems[i].time > oldestTime)
  778.                 {
  779.                         oldestTime = m_lastThrownItems[i].time;
  780.                         oldestId = i;
  781.                 }
  782.         }
  783.  
  784.         IEntity* pEnt = gEnv->pEntitySystem->GetEntity(id);
  785.         if (!pEnt)
  786.                 return;
  787.  
  788.         // The entity does not exists yet, add it to the list of entities to watch.
  789.         m_lastThrownItems.push_back(SThrownItem(id));
  790.  
  791.         // Skip the nearest thrown entity, since it is potentially blocking the view to the corpse.
  792.         IEntity* pThrownEnt = id ? gEnv->pEntitySystem->GetEntity(id) : 0;
  793.         CAIActor* pThrownActor = CastToCAIActorSafe(pThrownEnt->GetAI());
  794.         if (pThrownActor)
  795.         {
  796.                 short gid = (short)pThrownActor->GetGroupId();
  797.                 AIObjects::iterator ai = GetAISystem()->m_mapGroups.find(gid);
  798.                 AIObjects::iterator end = GetAISystem()->m_mapGroups.end();
  799.                 for (; ai != end && ai->first == gid; ++ai)
  800.                 {
  801.                         CPuppet* pPuppet = CastToCPuppetSafe(ai->second.GetAIObject());
  802.                         if (!pPuppet) continue;
  803.                         if (pPuppet->GetEntityID() == pThrownActor->GetEntityID()) continue;
  804.                         float dist = FLT_MAX;
  805.                         if (!GetAISystem()->CheckVisibilityToBody(pPuppet, pThrownActor, dist))
  806.                                 continue;
  807.                         pPuppet->SetSignal(1, "OnGroupMemberMutilated", pThrownActor->GetEntity(), 0);
  808.                         pPuppet->SetAlarmed();
  809.                 }
  810.         }
  811.  
  812.         // Set initial position, radius and velocity.
  813.         m_lastThrownItems.back().pos = pEnt->GetWorldPos();
  814.         AABB bounds;
  815.         pEnt->GetWorldBounds(bounds);
  816.         m_lastThrownItems.back().r = bounds.GetRadius();
  817.  
  818.         if (IPhysicalEntity* pPhysEnt = pEnt->GetPhysics())
  819.         {
  820.                 pe_status_dynamics statDyn;
  821.                 pPhysEnt->GetStatus(&statDyn);
  822.                 m_lastThrownItems.back().vel = statDyn.v;
  823.         }
  824.  
  825.         // Limit the number of hot entities.
  826.         if (m_lastThrownItems.size() > 4)
  827.         {
  828.                 m_lastThrownItems[oldestId] = m_lastThrownItems.back();
  829.                 m_lastThrownItems.pop_back();
  830.         }
  831. }
  832.  
  833. void CAIPlayer::HandleArmoredHit()
  834. {
  835.         NotifyPlayerActionToTheLookingAgents("OnTargetArmoredHit");
  836. }
  837.  
  838. void CAIPlayer::HandleCloaking(bool cloak)
  839. {
  840.         CAISystem* pAISystem = GetAISystem();
  841.  
  842.         m_Parameters.m_bCloaked = cloak;
  843.         m_Parameters.m_fLastCloakEventTime = pAISystem->GetFrameStartTime().GetSeconds();
  844.         NotifyPlayerActionToTheLookingAgents(cloak ? "OnTargetCloaked" : "OnTargetUncloaked");
  845. }
  846.  
  847. void CAIPlayer::HandleStampMelee()
  848. {
  849.         if (!m_Parameters.m_bCloaked)
  850.                 NotifyPlayerActionToTheLookingAgents("OnTargetStampMelee");
  851. }
  852.  
  853. //-----------------------------------------------------------
  854.  
  855. void CAIPlayer::NotifyPlayerActionToTheLookingAgents(const char* eventName)
  856. {
  857.         CAISystem* pAISystem = GetAISystem();
  858.         ActorLookUp& lookUp = *gAIEnv.pActorLookUp;
  859.         size_t activeCount = lookUp.GetActiveCount();
  860.  
  861.         // Notify AI who have the player as their target
  862.         EntityId playerId = GetEntityID();
  863.         for (size_t actorIndex = 0; actorIndex < activeCount; ++actorIndex)
  864.         {
  865.                 CAIActor* pAIActor = lookUp.GetActor<CAIActor>(actorIndex);
  866.  
  867.                 CAIObject* pTarget = static_cast<CAIObject*>(pAIActor ? pAIActor->GetAttentionTarget() : NULL);
  868.                 if (pTarget)
  869.                 {
  870.                         bool targetIsPlayer = (pTarget->GetEntityID() == playerId);
  871.                         VisionID targetVisionId = GetVisionID(); // This is the player vision id
  872.                         if (!targetIsPlayer)
  873.                         {
  874.                                 // Test association
  875.                                 CWeakRef<CAIObject> refAssociation = pTarget->GetAssociation();
  876.                                 CAIObject* pAssociation = (refAssociation.IsValid() ? refAssociation.GetAIObject() : NULL);
  877.                                 targetIsPlayer = (pAssociation && pAssociation->GetEntityID() == playerId);
  878.                                 if (targetIsPlayer)
  879.                                 {
  880.                                         targetVisionId = pAssociation->GetVisionID();
  881.                                 }
  882.                         }
  883.  
  884.                         if (targetIsPlayer)
  885.                         {
  886.                                 const bool bCanSeeTarget = pAIActor->CanSee(targetVisionId);
  887.                                 if (bCanSeeTarget)
  888.                                 {
  889.                                         AISignalExtraData* pData = new AISignalExtraData;
  890.                                         pData->nID = playerId;
  891.                                         pData->iValue = pAIActor->GetAttentionTargetType();
  892.                                         pData->iValue2 = pAIActor->GetAttentionTargetThreat();
  893.                                         pData->fValue = pAIActor->GetPos().GetDistance(GetPos());
  894.                                         pAISystem->SendSignal(SIGNALFILTER_SENDER, 1, eventName, pAIActor, pData);
  895.                                 }
  896.                         }
  897.                 }
  898.         }
  899. }
  900.  
  901. //-----------------------------------------------------------
  902.  
  903. void CAIPlayer::Event(unsigned short eType, SAIEVENT* pEvent)
  904. {
  905.         switch (eType)
  906.         {
  907.         case AIEVENT_AGENTDIED:
  908.                 // make sure everybody knows I have died
  909.                 GetAISystem()->NotifyTargetDead(this);
  910.                 m_bEnabled = false;
  911.                 GetAISystem()->RemoveFromGroup(GetGroupId(), this);
  912.  
  913.                 GetAISystem()->ReleaseFormationPoint(this);
  914.                 ReleaseFormation();
  915.  
  916.                 m_State.ClearSignals();
  917.  
  918.                 if (m_proxy)
  919.                         m_proxy->Reset(AIOBJRESET_SHUTDOWN);
  920.  
  921.                 SetObservable(false);
  922.                 break;
  923.         case AIEVENT_PLAYER_STUNT_SPRINT:
  924.                 m_playerStuntSprinting = PLAYER_ACTION_SPRINT_RESET_TIME;
  925.                 m_playerStuntJumping = -1.0f;
  926.                 break;
  927.         case AIEVENT_PLAYER_STUNT_JUMP:
  928.                 m_playerStuntJumping = PLAYER_ACTION_JUMP_RESET_TIME;
  929.                 m_playerStuntSprinting = -1.0f;
  930.                 break;
  931.         case AIEVENT_PLAYER_STUNT_PUNCH:
  932.                 if (pEvent)
  933.                         AddThrownEntity(pEvent->targetId);
  934.                 break;
  935.         case AIEVENT_PLAYER_STUNT_THROW:
  936.                 if (pEvent)
  937.                         AddThrownEntity(pEvent->targetId);
  938.                 break;
  939.         case AIEVENT_PLAYER_STUNT_THROW_NPC:
  940.                 if (pEvent)
  941.                         AddThrownEntity(pEvent->targetId);
  942.                 break;
  943.         case AIEVENT_PLAYER_THROW:
  944.                 if (pEvent)
  945.                         AddThrownEntity(pEvent->targetId);
  946.                 break;
  947.         case AIEVENT_PLAYER_STUNT_CLOAK:
  948.                 m_playerStuntCloaking = PLAYER_ACTION_CLOAK_RESET_TIME;
  949.                 HandleCloaking(true);
  950.                 break;
  951.         case AIEVENT_PLAYER_STUNT_UNCLOAK:
  952.                 m_playerStuntUncloaking = PLAYER_ACTION_CLOAK_RESET_TIME;
  953.                 HandleCloaking(false);
  954.                 break;
  955.         case AIEVENT_PLAYER_STUNT_ARMORED:
  956.                 HandleArmoredHit();
  957.                 break;
  958.         case AIEVENT_PLAYER_STAMP_MELEE:
  959.                 HandleStampMelee();
  960.                 break;
  961.         case AIEVENT_LOWHEALTH:
  962.                 {
  963.                         const float scale = (pEvent != NULL) ? pEvent->fThreat : 1.0f;
  964.                         m_mercyTimer = gAIEnv.CVars.RODLowHealthMercyTime * scale;
  965.                 }
  966.                 break;
  967.         case AIEVENT_ENABLE:
  968.                 SetObservable(true);
  969.                 MyBase::Event(eType, pEvent);
  970.                 break;
  971.         default:
  972.                 MyBase::Event(eType, pEvent);
  973.                 break;
  974.         }
  975. }
  976.  
  977. //
  978. //---------------------------------------------------------------------------------
  979. DamagePartVector* CAIPlayer::GetDamageParts()
  980. {
  981.         if (!m_damagePartsUpdated)
  982.         {
  983.                 UpdateDamageParts(m_damageParts);
  984.                 m_damagePartsUpdated = true;
  985.         }
  986.  
  987.         return &m_damageParts;
  988. }
  989.  
  990. //
  991. //----------------------------------------------------------------------------------------------
  992. void CAIPlayer::RecordSnapshot()
  993. {
  994.         // Currently not used
  995. }
  996.  
  997. //
  998. //----------------------------------------------------------------------------------------------
  999. void CAIPlayer::RecordEvent(IAIRecordable::e_AIDbgEvent event, const IAIRecordable::RecorderEventData* pEventData)
  1000. {
  1001. #ifdef CRYAISYSTEM_DEBUG
  1002.         CRecorderUnit* pRecord = (CRecorderUnit*)GetAIDebugRecord();
  1003.         if (pRecord != NULL)
  1004.         {
  1005.                 pRecord->RecordEvent(event, pEventData);
  1006.         }
  1007. #endif //CRYAISYSTEM_DEBUG
  1008. }
  1009.  
  1010. bool CAIPlayer::GetMissLocation(const Vec3& shootPos, const Vec3& shootDir, float maxAngle, Vec3& pos)
  1011. {
  1012. #if ENABLE_MISSLOCATION_SENSOR
  1013.         if (m_coolMissCooldown <= 0.000001f)
  1014.                 return m_pMissLocationSensor->GetLocation(this, shootPos, shootDir, maxAngle, pos);
  1015. #endif
  1016.  
  1017.         return false;
  1018. }
  1019.  
  1020. void CAIPlayer::NotifyMissLocationConsumed()
  1021. {
  1022.         m_coolMissCooldown += gAIEnv.CVars.CoolMissesCooldown;
  1023. }
  1024.  
  1025. //
  1026. //---------------------------------------------------------------------------------
  1027. void CAIPlayer::DebugDraw()
  1028. {
  1029.         CDebugDrawContext dc;
  1030.  
  1031.         // Draw items associated with player actions.
  1032.         for (unsigned i = 0, ni = m_lastThrownItems.size(); i < ni; ++i)
  1033.         {
  1034.                 //              IEntity* pEnt = gEnv->pEntitySystem->GetEntity(m_lastThrownItems[i].id);
  1035.                 //              if (pEnt)
  1036.                 {
  1037.                         /*                      AABB bounds;
  1038.                               pEnt->GetWorldBounds(bounds);
  1039.                               dc->DrawAABB(bounds, false, ColorB(255, 0, 0), eBBD_Faceted);
  1040.                               bounds.Move(m_lastThrownItems[i].vel);
  1041.                               dc->DrawAABB(bounds, false, ColorB(255, 0, 0, 128), eBBD_Faceted);*/
  1042.  
  1043.                         AABB bounds(AABB::RESET);
  1044.                         bounds.Add(m_lastThrownItems[i].pos, m_lastThrownItems[i].r);
  1045.                         dc->DrawAABB(bounds, false, ColorB(255, 0, 0), eBBD_Faceted);
  1046.                         bounds.Move(m_lastThrownItems[i].vel);
  1047.                         dc->DrawLine(m_lastThrownItems[i].pos, ColorB(255, 0, 0), m_lastThrownItems[i].pos + m_lastThrownItems[i].vel, ColorB(255, 0, 0, 128));
  1048.                         dc->DrawAABB(bounds, false, ColorB(255, 0, 0, 128), eBBD_Faceted);
  1049.  
  1050.                         //                      Vec3 dir = m_lastThrownItems[i].vel;
  1051.                         //                      float speed = dir.NormalizeSafe(Vec3(1,0,0));
  1052.  
  1053.                         /*                      float speed = m_lastThrownItems[i].vel.GetLength();
  1054.                               if (speed > 0.0f)
  1055.                               {
  1056.                               }
  1057.                               else
  1058.                               {
  1059.                               }*/
  1060.                 }
  1061.         }
  1062.  
  1063.         for (unsigned i = 0, ni = m_stuntTargets.size(); i < ni; ++i)
  1064.         {
  1065.                 const SAIBodyInfo& bodyInfo = m_stuntTargets[i].pAIActor->GetBodyInfo();
  1066.                 Vec3 pos = m_stuntTargets[i].pAIActor->GetPhysicsPos();
  1067.                 AABB aabb(bodyInfo.stanceSize);
  1068.                 aabb.Move(pos);
  1069.                 dc->DrawAABB(aabb, true, ColorB(255, 255, 255, m_stuntTargets[i].signalled ? 128 : 48), eBBD_Faceted);
  1070.         }
  1071.  
  1072.         ColorB color(255, 255, 255);
  1073.  
  1074.         // Draw special player actions
  1075.         if (m_playerStuntSprinting > 0.0f)
  1076.         {
  1077.                 Vec3 pos = GetPos();
  1078.                 Vec3 vel = GetVelocity();
  1079.                 const SAIBodyInfo& bi = GetBodyInfo();
  1080.                 float r = bi.stanceSize.GetRadius();
  1081.                 AABB bounds(AABB::RESET);
  1082.                 bounds.Add(pos, r);
  1083.                 dc->DrawAABB(bounds, false, ColorB(255, 0, 0), eBBD_Faceted);
  1084.                 bounds.Move(vel);
  1085.                 dc->DrawLine(pos, ColorB(255, 0, 0), pos + vel, ColorB(255, 0, 0, 128));
  1086.                 dc->DrawAABB(bounds, false, ColorB(255, 0, 0, 128), eBBD_Faceted);
  1087.  
  1088.                 // [2/27/2009 evgeny] Here and below in this method,
  1089.                 // first argument for Draw2dLabel was 10, not 100, and the text was hardly visible
  1090.                 dc->Draw2dLabel(100, 10, 2.5f, color, true, "SPRINTING");
  1091.         }
  1092.         if (m_playerStuntJumping > 0.0f)
  1093.         {
  1094.                 Vec3 pos = GetPos();
  1095.                 Vec3 vel = GetVelocity();
  1096.                 const SAIBodyInfo& bi = GetBodyInfo();
  1097.                 float r = bi.stanceSize.GetRadius();
  1098.                 AABB bounds(AABB::RESET);
  1099.                 bounds.Add(pos, r);
  1100.                 dc->DrawAABB(bounds, false, ColorB(255, 0, 0), eBBD_Faceted);
  1101.                 bounds.Move(vel);
  1102.                 dc->DrawLine(pos, ColorB(255, 0, 0), pos + vel, ColorB(255, 0, 0, 128));
  1103.                 dc->DrawAABB(bounds, false, ColorB(255, 0, 0, 128), eBBD_Faceted);
  1104.  
  1105.                 dc->Draw2dLabel(100, 40, 2.5f, color, true, "JUMPING");
  1106.         }
  1107.         if (m_playerStuntCloaking > 0.0f)
  1108.         {
  1109.                 dc->Draw2dLabel(100, 70, 2.5f, color, true, "CLOAKING");
  1110.         }
  1111.         if (m_playerStuntUncloaking > 0.0f)
  1112.         {
  1113.                 dc->Draw2dLabel(100, 110, 2.5f, color, true, "UNCLOAKING");
  1114.         }
  1115.         if (!m_lastThrownItems.empty())
  1116.         {
  1117.                 dc->Draw2dLabel(100, 150, 2.5f, color, true, "THROWING");
  1118.         }
  1119.  
  1120.         if (IsLowHealthPauseActive())
  1121.         {
  1122.                 ICVar* pLowHealth = gEnv->pConsole->GetCVar("g_playerLowHealthThreshold");
  1123.                 dc->Draw2dLabel(150, 190, 2.0f, color, true, "Mercy %.2f/%.2f (when below %0.2f)", m_mercyTimer, gAIEnv.CVars.RODLowHealthMercyTime, pLowHealth->GetFVal());
  1124.         }
  1125.  
  1126.         for (unsigned i = 0, ni = m_exposedCoverObjects.size(); i < ni; ++i)
  1127.         {
  1128.                 pe_status_pos statusPos;
  1129.                 m_exposedCoverObjects[i].pPhysEnt->GetStatus(&statusPos);
  1130.                 AABB bounds(AABB::RESET);
  1131.                 bounds.Add(statusPos.BBox[0] + statusPos.pos);
  1132.                 bounds.Add(statusPos.BBox[1] + statusPos.pos);
  1133.                 dc->DrawAABB(bounds, false, ColorB(255, 0, 0), eBBD_Faceted);
  1134.                 dc->Draw3dLabel(bounds.GetCenter(), 1.1f, "IGNORED %.1fs", m_exposedCoverObjects[i].t);
  1135.         }
  1136. }
  1137.  
  1138. //
  1139. //---------------------------------------------------------------------------------
  1140. bool CAIPlayer::IsLowHealthPauseActive() const
  1141. {
  1142.         if (m_mercyTimer > 0.0f)
  1143.                 return true;
  1144.         return false;
  1145. }
  1146.  
  1147. //
  1148. //------------------------------------------------------------------------------------------------------------------------
  1149. IEntity* CAIPlayer::GetGrabbedEntity() const
  1150. {
  1151.         IAIActorProxy* pProxy = GetProxy();
  1152.  
  1153.         return pProxy ? pProxy->GetGrabbedEntity() : NULL;
  1154. }
  1155.  
  1156. //
  1157. //------------------------------------------------------------------------------------------------------------------------
  1158. bool CAIPlayer::IsGrabbedEntityInView(const Vec3& pos) const
  1159. {
  1160.         bool bInViewDist = true;
  1161.  
  1162.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  1163.         assert(pEntitySystem);
  1164.  
  1165.         IEntity* pObjectEntity = GetGrabbedEntity();
  1166.  
  1167.         IEntityRender* pObjectRenderProxy = (pObjectEntity ? (pObjectEntity->GetRenderInterface()) : NULL);
  1168.         if (pObjectRenderProxy)
  1169.         {
  1170.                 IRenderNode* pObjectRenderNode = pObjectRenderProxy->GetRenderNode();
  1171.                 if (pObjectRenderNode)
  1172.                 {
  1173.                         const float fDistanceSq = pos.GetSquaredDistance(pObjectEntity->GetWorldPos());
  1174.                         const float fMinDist = 4.0f;
  1175.                         const float fMaxViewDistSq = sqr(max(pObjectRenderNode->GetMaxViewDist(), fMinDist));
  1176.  
  1177.                         bInViewDist = (fDistanceSq <= fMaxViewDistSq);
  1178.                 }
  1179.         }
  1180.  
  1181.         return bInViewDist;
  1182. }
  1183.  
  1184. //
  1185. //---------------------------------------------------------------------------------
  1186. void CAIPlayer::Serialize(TSerialize ser)
  1187. {
  1188.         ser.BeginGroup("AIPlayer");
  1189.  
  1190.         MyBase::Serialize(ser);
  1191.  
  1192.         ser.Value("m_fLastUpdateTargetTime", m_fLastUpdateTargetTime);
  1193.         ser.Value("m_FOV", m_FOV);
  1194.  
  1195.         ser.Value("m_playerStuntSprinting", m_playerStuntSprinting);
  1196.         ser.Value("m_playerStuntJumping", m_playerStuntJumping);
  1197.         ser.Value("m_playerStuntCloaking", m_playerStuntCloaking);
  1198.         ser.Value("m_playerStuntUncloaking", m_playerStuntUncloaking);
  1199.         ser.Value("m_stuntDir", m_stuntDir);
  1200.         ser.ValueWithDefault("m_mercyTimer", m_mercyTimer, -1.0f);
  1201.  
  1202.         ser.EndGroup();
  1203. }
  1204.  
downloadAIPlayer.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top