BVB Source Codes

CRYENGINE Show PuppetPhys.cpp Source code

Return Download CRYENGINE: download PuppetPhys.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:   PuppetPhys.cpp
  6.    $Id$
  7.    Description: should contaioin all the methods of CPuppet which have to deal with Physics
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    - 2007                               : Created by Kirill Bulatsev
  12.    - 4 May 2009  : Evgeny Adamenkov: Removed IRenderer
  13.  
  14.  *********************************************************************/
  15.  
  16. #include "StdAfx.h"
  17. #include "Puppet.h"
  18. #include "AILog.h"
  19. #include "GoalOp.h"
  20. #include "Graph.h"
  21. #include "AIPlayer.h"
  22. #include "Leader.h"
  23. #include "CAISystem.h"
  24. #include "AICollision.h"
  25. #include "VertexList.h"
  26. #include "SmartObjects.h"
  27. #include "PathFollower.h"
  28. #include "AIVehicle.h"
  29.  
  30. #include <CrySystem/IConsole.h>
  31. #include <CryPhysics/IPhysics.h>
  32. #include <CrySystem/ISystem.h>
  33. #include <CrySystem/ILog.h>
  34. #include <CrySystem/ITimer.h>
  35. #include <Cry3DEngine/I3DEngine.h>
  36. #include <CryNetwork/ISerialize.h>
  37.  
  38. //#pragma optimize("", off)
  39. //#pragma inline_depth(0)
  40.  
  41. std::vector<std::pair<float, size_t>> CPuppet::s_weights;
  42.  
  43. // Helper structure to sort indices pointing to an array of weights.
  44. struct SDamageLUTSorter
  45. {
  46.         SDamageLUTSorter(const std::vector<float>& values) : m_values(values) {}
  47.         bool operator()(int lhs, int rhs) const { return m_values[lhs] < m_values[rhs]; }
  48.         const std::vector<float>& m_values;
  49. };
  50.  
  51. //====================================================================
  52. // ActorObstructingAim
  53. //====================================================================
  54. bool CPuppet::ActorObstructingAim(const CAIActor* pActor, const Vec3& firePos, const Vec3& dir, const Ray& fireRay) const
  55. {
  56.         IF_UNLIKELY (!pActor)
  57.                 return false;
  58.  
  59.         const Vec3 normalizedFireDirectionXY = Vec3(dir.x, dir.y, 0.0f).GetNormalizedSafe();
  60.         Vec3 directionFromFirePositionToOtherAgentPosition = pActor->GetPhysicsPos() - firePos;
  61.         directionFromFirePositionToOtherAgentPosition.z = 0.0f;
  62.         directionFromFirePositionToOtherAgentPosition.NormalizeSafe();
  63.  
  64.         static float threshold = cosf(DEG2RAD(35.0f));
  65.         if (normalizedFireDirectionXY.Dot(directionFromFirePositionToOtherAgentPosition) > threshold)
  66.         {
  67.                 // Check if ray intersects with other agent's bounding box
  68.                 if (IPhysicalEntity* actorPhysics = pActor->GetPhysics())
  69.                 {
  70.                         pe_status_pos ppos;
  71.  
  72.                         if (actorPhysics->GetStatus(&ppos))
  73.                         {
  74.                                 Vec3 point;
  75.                                 AABB box(ppos.pos + ppos.BBox[0], ppos.pos + ppos.BBox[1]);
  76.                                 if (Intersect::Ray_AABB(fireRay, box, point))
  77.                                 {
  78.                                         return true;
  79.                                 }
  80.                         }
  81.                 }
  82.         }
  83.  
  84.         return false;
  85. }
  86.  
  87. //====================================================================
  88. // CanAimWithoutObstruction
  89. //====================================================================
  90. bool CPuppet::CanAimWithoutObstruction(const Vec3& vTargetPos)
  91. {
  92.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  93.  
  94.         if (m_bDryUpdate)
  95.                 return m_lastAimObstructionResult;
  96.  
  97.         const float checkDistance = GetPos().GetDistance(vTargetPos) * 0.5f;
  98.         const float softCheckDistance = 0.5f;
  99.         const bool bResult = CheckLineOfFire(vTargetPos, checkDistance, softCheckDistance);
  100.  
  101.         m_lastAimObstructionResult = bResult;
  102.         return bResult;
  103. }
  104.  
  105. void CPuppet::LineOfFireRayComplete(const QueuedRayID& rayID, const RayCastResult& result)
  106. {
  107.         m_lineOfFireState.asyncState = AsyncReady;
  108.         m_lineOfFireState.rayID = 0;
  109.  
  110.         m_lineOfFireState.result = true;
  111.         if (result)
  112.         {
  113.                 m_lineOfFireState.result = false;
  114.  
  115.                 pe_status_pos stat;
  116.                 if (result[0].pCollider && result[0].pCollider->GetStatus(&stat))
  117.                 {
  118.                         if ((stat.flagsOR & geom_colltype_obstruct))
  119.                                 m_lineOfFireState.result = !(result[0].dist < m_lineOfFireState.softDistance);
  120.                 }
  121.         }
  122. }
  123.  
  124. //====================================================================
  125. // CheckLineOfFire
  126. //====================================================================
  127. bool CPuppet::CheckLineOfFire(const Vec3& vTargetPos, float fDistance, float fSoftDistance, EStance stance /*= STANCE_NULL*/) const
  128. {
  129.         CRY_ASSERT(vTargetPos.IsValid());
  130.  
  131.         bool bResult = true;
  132.  
  133.         // Early outs
  134.         IAIActorProxy* pProxy = GetProxy();
  135.         assert(pProxy);//shut up SCA
  136.         if ((pProxy && pProxy->GetLinkedVehicleEntityId()) || GetSubType() == CAIObject::STP_2D_FLY)
  137.                 return true;
  138.  
  139.         ActorLookUp& lookUp = *gAIEnv.pActorLookUp;
  140.         lookUp.Prepare(ActorLookUp::Position);
  141.  
  142.         SAIBodyInfo bodyInfo;
  143.         const Vec3& firePos = (stance > STANCE_NULL && pProxy->QueryBodyInfo(SAIBodyInfoQuery(stance, 0.0f, 0.0f, true), bodyInfo) ? bodyInfo.vFirePos : GetFirePos());
  144.         Vec3 dir = vTargetPos - firePos;
  145.  
  146.         Ray fireRay(firePos, dir);
  147.         Vec3 pos = GetPos();
  148.  
  149.         size_t activeActorCount = lookUp.GetActiveCount();
  150.  
  151.         for (size_t actorIndex = 0; actorIndex < activeActorCount; ++actorIndex)
  152.         {
  153.                 CAIActor* pAIActor = lookUp.GetActor<CAIActor>(actorIndex);
  154.                 if (pAIActor == this)
  155.                         continue;
  156.  
  157.                 if (Distance::Point_PointSq(pos, lookUp.GetPosition(actorIndex)) > sqr(10.0f))
  158.                         continue;
  159.  
  160.                 if (!IsHostile(pAIActor) && ActorObstructingAim(pAIActor, firePos, dir, fireRay))
  161.                 {
  162.                         bResult = false;
  163.                         break;
  164.                 }
  165.         }
  166.  
  167.         if (bResult)
  168.         {
  169.                 //check the player (friends only)
  170.                 CAIActor* pPlayer(CastToCAIActorSafe(GetAISystem()->GetPlayer()));
  171.                 if (pPlayer)
  172.                 {
  173.                         if (!IsHostile(pPlayer) &&
  174.                             Distance::Point_PointSq(GetPos(), pPlayer->GetPos()) < sqr(5.0f) &&
  175.                             ActorObstructingAim(pPlayer, firePos, dir, fireRay))
  176.                         {
  177.                                 bResult = false;
  178.                         }
  179.                 }
  180.         }
  181.  
  182.         if (bResult && m_fireMode != FIREMODE_KILL && fDistance > FLT_EPSILON) // when in KILL mode - just shoot no matter what
  183.         {
  184.                 dir.Normalize();
  185.                 dir *= fDistance;
  186.  
  187.                 m_lineOfFireState.softDistance = fSoftDistance;
  188.  
  189.                 if (m_lineOfFireState.asyncState == AsyncReady)
  190.                 {
  191.                         m_lineOfFireState.asyncState = AsyncInProgress;
  192.  
  193.                         PhysSkipList skipList;
  194.                         GetPhysicalSkipEntities(skipList);
  195.  
  196.                         // Add the physical body of the target to the skip list.
  197.                         if (IAIObject* pTarget = GetAttentionTarget())
  198.                         {
  199.                                 // If the target is a memory or a sound, then use the physics
  200.                                 // from the association (the real entity running around.)
  201.                                 if (IAIObject* pAssociation = GetAttentionTargetAssociation())
  202.                                         pTarget = pAssociation;
  203.  
  204.                                 if (IEntity* pEntity = pTarget->GetEntity())
  205.                                 {
  206.                                         if (IPhysicalEntity* pPhysicalEntity = pEntity->GetPhysics())
  207.                                                 stl::push_back_unique(skipList, pPhysicalEntity);
  208.                                 }
  209.                         }
  210.  
  211.                         m_lineOfFireState.rayID = gAIEnv.pRayCaster->Queue(RayCastRequest::HighestPriority,
  212.                                                                            RayCastRequest(
  213.                                                                              firePos, dir, COVER_OBJECT_TYPES,
  214.                                                                              AI_VISION_RAY_CAST_FLAG_BLOCKED_BY_SOLID_COVER,
  215.                                                                              &skipList[0], skipList.size()),
  216.                                                                            functor(const_cast<CPuppet&>(*this), &CPuppet::LineOfFireRayComplete));
  217.                 }
  218.  
  219.                 return m_lineOfFireState.result;
  220.         }
  221.  
  222.         return bResult;
  223. }
  224.  
  225. //====================================================================
  226. // ClampPointInsideCone
  227. //====================================================================
  228. static void ClampPointInsideCone(const Vec3& conePos, const Vec3& coneDir, float coneAngle, Vec3& pos)
  229. {
  230.         Vec3 dirToPoint = pos - conePos;
  231.         float distOnLine = coneDir.Dot(dirToPoint);
  232.         if (distOnLine < 0.0f)
  233.         {
  234.                 pos = conePos;
  235.                 AILogComment("ClampPointInsideCone(): Point clamped distOnLine = %f", distOnLine);
  236.                 return;
  237.         }
  238.  
  239.         Vec3 pointOnLine = coneDir * distOnLine;
  240.  
  241.         const float dmax = tanf(coneAngle) * distOnLine + 0.75f;
  242.  
  243.         Vec3 diff = dirToPoint - pointOnLine;
  244.         float d = diff.NormalizeSafe();
  245.  
  246.         if (d > dmax)
  247.         {
  248.                 pos = conePos + pointOnLine + diff * dmax;
  249.                 AILogComment("ClampPointInsideCone(): Point clamped d = %f, dmax = %f", d, dmax);
  250.         }
  251. }
  252.  
  253. ILINE Vec3 JitterVector(Vec3 v, Vec3 amount)
  254. {
  255.         return Vec3(
  256.           v.x + cry_random(-amount.x, amount.x),
  257.           v.y + cry_random(-amount.y, amount.y),
  258.           v.z + cry_random(-amount.z, amount.z));
  259. }
  260.  
  261. //====================================================================
  262. // CheckAndAdjustFireTarget
  263. //====================================================================
  264. bool CPuppet::AdjustFireTarget(CAIObject* targetObject, const Vec3& target, bool hit, float missExtraOffset,
  265.                                float clampAngle, Vec3* posOut)
  266. {
  267.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  268.  
  269.         Vec3 out(target);
  270.  
  271.         if (hit)
  272.         {
  273.                 if (!CalculateHitPointOnTarget(targetObject, target, clampAngle, &out))
  274.                 {
  275.                         out = JitterVector(target, Vec3(0.05f));
  276.                         AdjustWithPrediction(targetObject, out);
  277.                 }
  278.  
  279.                 m_targetLastMissPoint = out;
  280.  
  281.                 if (IsFireTargetValid(out, targetObject))
  282.                 {
  283.                         *posOut = out;
  284.  
  285.                         return true;
  286.                 }
  287.  
  288.                 m_lastHitShotsCount = ~0l;
  289.         }
  290.         else
  291.         {
  292.                 size_t shotsCount = m_pFireCmdHandler ? (size_t)m_pFireCmdHandler->GetShotCount() : 0;
  293.                 if (m_lastMissShotsCount == shotsCount && STP_HELICRYSIS2 != GetSubType())
  294.                         out = m_targetLastMissPoint;
  295.                 else
  296.                 {
  297.                         bool found = false;
  298.  
  299.                         if (targetObject && gAIEnv.CVars.EnableCoolMisses && cry_random(0.0f, 1.0f) < gAIEnv.CVars.CoolMissesProbability)
  300.                         {
  301.                                 if (CAIPlayer* player = targetObject->CastToCAIPlayer())
  302.                                 {
  303.                                         Vec3 fireLocation = GetFirePos();
  304.                                         Vec3 dir = target - fireLocation;
  305.  
  306.                                         float distance = dir.NormalizeSafe();
  307.  
  308.                                         if (distance >= gAIEnv.CVars.CoolMissesMinMissDistance)
  309.                                                 found = player->GetMissLocation(fireLocation, dir, clampAngle, out);
  310.                                 }
  311.                         }
  312.  
  313.                         found = found || CalculateMissPointOutsideTargetSilhouette(targetObject, target, missExtraOffset, &out);
  314.  
  315.                         if (!found)
  316.                                 out = JitterVector(target, Vec3(0.15f));
  317.                 }
  318.  
  319.                 m_targetLastMissPoint = out;
  320.  
  321.                 if (IsFireTargetValid(out, targetObject))
  322.                 {
  323.                         m_lastMissShotsCount = shotsCount;
  324.                         m_targetEscapeLastMiss = clamp_tpl(m_targetEscapeLastMiss - 0.1f, 0.0f, 1.0f);
  325.                         *posOut = out;
  326.  
  327.                         return true;
  328.                 }
  329.  
  330.                 m_lastMissShotsCount = ~0l;
  331.                 m_targetEscapeLastMiss = clamp_tpl(m_targetEscapeLastMiss + 0.1f, 0.0f, 1.0f);
  332.         }
  333.  
  334.         *posOut = out;
  335.  
  336.         return false;
  337. }
  338.  
  339. //====================================================================
  340. // DeltaAngle
  341. // returns delta angle from a to b in -PI..PI
  342. //====================================================================
  343. inline float DeltaAngle(float a, float b)
  344. {
  345.         float d = b - a;
  346.         d = fmodf(d, gf_PI2);
  347.         if (d < -gf_PI) d += gf_PI2;
  348.         if (d > gf_PI) d -= gf_PI2;
  349.         return d;
  350. };
  351.  
  352. bool CPuppet::CalculateMissPointOutsideTargetSilhouette(CAIObject* targetObject, const Vec3& target, float missExtraOffset,
  353.                                                         Vec3* posOut)
  354. {
  355.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  356.  
  357.         if (m_targetSilhouette.valid)
  358.         {
  359.                 const Vec3 silhouettePlanePoint = m_targetSilhouette.IntersectSilhouettePlane(GetFirePos(), target);
  360.                 const Vec3 silhouettePoint = m_targetSilhouette.ProjectVectorOnSilhouette(silhouettePlanePoint - m_targetSilhouette.center);
  361.  
  362.                 if (Overlap::Point_Polygon2D(silhouettePoint, m_targetSilhouette.points))
  363.                 {
  364.                         const Vec3 bias = m_targetSilhouette.ProjectVectorOnSilhouette(m_targetBiasDirection)
  365.                                           .GetNormalizedSafe(Vec3(0.0f, 0.0f, 0.0f));
  366.                         const float spread = DEG2RAD(60.0f - 50.0f * m_targetFocus);
  367.                         const float angleLimit = DEG2RAD(50.0f);
  368.  
  369.                         float angle = (1.5f * atan2_tpl(bias.y, bias.x)) + cry_random(-1.0f, 1.0f) * spread * 0.5f;
  370.  
  371.                         if (!m_targetLastMissPoint.IsZero())
  372.                         {
  373.                                 const Vec3 lastMiss = m_targetSilhouette.ProjectVectorOnSilhouette(m_targetLastMissPoint - m_targetSilhouette.center);
  374.  
  375.                                 float lastMissAngle = atan2_tpl(lastMiss.y, lastMiss.x);
  376.                                 float deltaAngle = DeltaAngle(lastMissAngle, angle);
  377.  
  378.                                 Limit(deltaAngle, -angleLimit, angleLimit);
  379.                                 angle = lastMissAngle + deltaAngle;
  380.                         }
  381.  
  382.                         Vec3 pt;
  383.                         Vec3 dir(cos_tpl(angle), sin_tpl(angle), 0.0f);
  384.  
  385.                         if (Intersect::Lineseg_Polygon2D(Lineseg(ZERO, dir * 100.0f), m_targetSilhouette.points, pt))
  386.                         {
  387.                                 const Vec3 u = m_targetSilhouette.baseMtx.GetColumn0();
  388.                                 const Vec3 v = m_targetSilhouette.baseMtx.GetColumn2();
  389.  
  390.                                 Vec3 missTarget = m_targetSilhouette.center +
  391.                                                   u * (pt.x + dir.x * missExtraOffset) + v * (pt.y + dir.y * missExtraOffset);
  392.  
  393.                                 if (missTarget.z >= target.z + 0.15f)
  394.                                         missTarget.z -= (missTarget.z - target.z);
  395.  
  396.                                 *posOut = missTarget;
  397.  
  398.                                 return true;
  399.                         }
  400.                 }
  401.  
  402.                 *posOut = target;
  403.  
  404.                 return true;
  405.         }
  406.  
  407.         return false;
  408. }
  409.  
  410. //====================================================================
  411. // GetHitPointOnTarget
  412. //====================================================================
  413. bool CPuppet::CalculateHitPointOnTarget(CAIObject* targetObject, const Vec3& target, float clampAngle, Vec3* posOut)
  414. {
  415.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  416.  
  417.         if (!targetObject->IsAgent())
  418.                 return false;
  419.  
  420.         CAIActor* targetActor = targetObject->CastToCAIActor();
  421.         if (!targetActor)
  422.                 return false;
  423.  
  424.         if (!targetActor->GetDamageParts())
  425.                 return false;
  426.  
  427.         const DamagePartVector& parts = *targetActor->GetDamageParts();
  428.         size_t partCount = parts.size();
  429.  
  430.         if (!partCount)
  431.                 return false;
  432.  
  433.         if (m_fireMode == FIREMODE_KILL)
  434.         {
  435.                 float maxMult = 0.0f;
  436.  
  437.                 for (size_t i = 0; i < partCount; ++i)
  438.                 {
  439.                         if (parts[i].damageMult > maxMult)
  440.                         {
  441.                                 *posOut = parts[i].pos;
  442.                                 maxMult = parts[i].damageMult;
  443.                         }
  444.                 }
  445.  
  446.                 return maxMult > 0.0f;
  447.         }
  448.  
  449.         const Vec3 FireLocation = GetFirePos();
  450.         Vec3 pos;
  451.  
  452.         size_t shotsCount = m_pFireCmdHandler ? (size_t)m_pFireCmdHandler->GetShotCount() : 0;
  453.         if ((m_lastTargetPart < partCount) && (m_lastHitShotsCount == shotsCount))
  454.         {
  455.                 pos = parts[m_lastTargetPart].pos;
  456.         }
  457.         else
  458.         {
  459.                 m_lastHitShotsCount = shotsCount;
  460.  
  461.                 s_weights.clear();
  462.                 s_weights.resize(partCount);
  463.  
  464.                 const Lineseg LineOfFire(FireLocation, target);
  465.  
  466.                 float t;
  467.                 for (size_t i = 0; i < partCount; ++i)
  468.                         s_weights[i] = std::make_pair(Distance::Point_LinesegSq(parts[i].pos, LineOfFire, t), i);
  469.  
  470.                 std::sort(s_weights.begin(), s_weights.end());
  471.  
  472.                 size_t considerCount = std::min<size_t>(8, partCount);
  473.                 assert(considerCount > 0);
  474.  
  475.                 size_t targetPart = s_weights[cry_random((size_t)0, considerCount - 1)].second;
  476.                 m_lastTargetPart = targetPart;
  477.                 pos = parts[targetPart].pos;
  478.         }
  479.  
  480.         const float jitterAmount = 0.075f;
  481.         pos = JitterVector(pos, Vec3(jitterAmount));
  482.  
  483.         // Luciano: add prediction based on bullet and target speeds
  484.         AdjustWithPrediction(targetActor, pos);
  485.  
  486.         Vec3 dir = m_State.vAimTargetPos - FireLocation;
  487.         dir.Normalize();
  488.  
  489.         const SAIBodyInfo& bodyInfo = GetBodyInfo();
  490.         if (IEntity* pLinkedVehicleEntity = bodyInfo.GetLinkedVehicleEntity())
  491.         {
  492.                 if (pLinkedVehicleEntity->HasAI())
  493.                 {
  494.                         if (dir.Dot(bodyInfo.vFireDir) < cos_tpl(clampAngle))
  495.                                 return false;
  496.                 }
  497.         }
  498.  
  499.         *posOut = pos;
  500.  
  501.         return true;
  502. }
  503.  
  504. //====================================================================
  505. // AdjustWithPrediction
  506. //====================================================================
  507. void CPuppet::AdjustWithPrediction(CAIObject* pTarget, Vec3& posOut)
  508. {
  509.         if (!pTarget || (GetSubType() == CAIObject::STP_2D_FLY))
  510.                 return;
  511.  
  512.         float sp = m_CurrentWeaponDescriptor.fSpeed;//bullet speed
  513.         if (sp > 0.0f)
  514.         {
  515.                 if (pTarget->GetPhysics())
  516.                 {
  517.                         pe_status_dynamics dyn;
  518.                         pTarget->GetPhysics()->GetStatus(&dyn);
  519.  
  520.                         Vec3 Q(GetFirePos());
  521.                         Vec3 X0(posOut - Q);
  522.                         Vec3 V(dyn.v);//target velocity
  523.                         // solve a 2nd degree equation in t = time at which bullet and target will collide given their velocities
  524.                         float x0v = X0.Dot(V);
  525.                         float v02 = V.GetLengthSquared();
  526.                         float w02 = sp * sp;
  527.                         float x02 = X0.GetLengthSquared();
  528.                         float b = x0v;
  529.                         float sq = x0v * x0v - x02 * (v02 - w02);
  530.                         if (sq < 0)// bullet can't reach the target
  531.                                 return;
  532.  
  533.                         sq = sqrt(sq);
  534.                         float d = (v02 - w02);
  535.                         float t = (-b + sq) / d;
  536.                         float t1 = (-b - sq) / d;
  537.                         if (t < 0 && t1 > 0 || t1 > 0 && t1 < t)
  538.                                 t = t1;
  539.                         if (t < 0)
  540.                                 return;
  541.                         Vec3 W(X0 / t + V);//bullet velocity
  542.  
  543.                         posOut = Q + W * t;
  544.                         //GetAISystem()->AddDebugLine(Q,posOut,255,255,255,3);
  545.                 }
  546.         }
  547. }
  548.  
  549. bool CPuppet::IsFireTargetValid(const Vec3& targetPos, const CAIObject* pTargetObject)
  550. {
  551.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  552.  
  553.         // Accept the point if:
  554.         // 1) Shooting in the direction hits something relatively far away
  555.         // 2) There are no friendly units between the shooter and the target
  556.  
  557.         const Vec3& firePos = GetFirePos();
  558.         Vec3 fireDir = targetPos - firePos;
  559.  
  560.         if (m_fireMode != FIREMODE_BURST_DRAWFIRE)
  561.         {
  562.                 const float fireDirLen = fireDir.NormalizeSafe();
  563.  
  564.                 const float minCheckDist = 1.0f;
  565.                 const float maxCheckDist = 15.0f;
  566.                 const float requiredTravelDistPercent = 0.25f;
  567.                 const float requiredDist = clamp_tpl(fireDirLen * requiredTravelDistPercent, minCheckDist, maxCheckDist);
  568.  
  569.                 if (m_validTargetState.asyncState == AsyncReady)
  570.                         QueueFireTargetValidRay(pTargetObject, firePos, fireDir * requiredDist);
  571.  
  572.                 if (m_validTargetState.latestHitDist < requiredDist)
  573.                         return false;
  574.         }
  575.  
  576.         return !CheckFriendsInLineOfFire(fireDir, false);
  577. }
  578.  
  579. void CPuppet::QueueFireTargetValidRay(const CAIObject* targetObj, const Vec3& firePos, const Vec3& fireDir)
  580. {
  581.         m_validTargetState.asyncState = AsyncInProgress;
  582.  
  583.         PhysSkipList skipList;
  584.         GetPhysicalSkipEntities(skipList);
  585.  
  586.         if (targetObj)
  587.         {
  588.                 if (targetObj->IsAgent())
  589.                 {
  590.                         if (const CAIActor* targetActor = targetObj->CastToCAIActor())
  591.                                 targetActor->GetPhysicalSkipEntities(skipList);
  592.                 }
  593.                 else if (IPhysicalEntity* physicalEnt = targetObj->GetPhysics())
  594.                 {
  595.                         stl::push_back_unique(skipList, physicalEnt);
  596.                 }
  597.         }
  598.  
  599.         m_validTargetState.rayID = gAIEnv.pRayCaster->Queue(
  600.           RayCastRequest::HighestPriority,
  601.           RayCastRequest(
  602.             firePos, fireDir, COVER_OBJECT_TYPES,
  603.             AI_VISION_RAY_CAST_FLAG_BLOCKED_BY_SOLID_COVER,
  604.             &skipList[0], skipList.size()),
  605.           functor(*this, &CPuppet::FireTargetValidRayComplete));
  606. }
  607.  
  608. void CPuppet::FireTargetValidRayComplete(const QueuedRayID& rayID, const RayCastResult& result)
  609. {
  610.         if (m_validTargetState.rayID == rayID)
  611.         {
  612.                 m_validTargetState.rayID = 0;
  613.                 m_validTargetState.asyncState = AsyncReady;
  614.  
  615.                 m_validTargetState.latestHitDist = result ? result[0].dist : FLT_MAX;
  616.         }
  617. }
  618.  
  619. //====================================================================
  620. // ChooseMissPoint
  621. //====================================================================
  622. Vec3 CPuppet::ChooseMissPoint_Deprecated(const Vec3& vTargetPos) const
  623. {
  624.         CCCPOINT(CPuppet_ChooseMissPoint_Deprecated);
  625.  
  626.         int trysLimit(5); // how many times try to get good point to shoot
  627.  
  628.         Vec3 dir(vTargetPos - GetFirePos());
  629.         float distToTarget = dir.len();
  630.         if (distToTarget > 0.00001f)
  631.                 dir /= distToTarget;
  632.  
  633.         Matrix33 mat(Matrix33::CreateRotationXYZ(Ang3::GetAnglesXYZ(Quat::CreateRotationVDir(dir))));
  634.         Vec3 right(mat.GetColumn(0));
  635.         //          Vec3 up(b3DTarget ? mat.GetColumn(2).normalize(): ZERO);
  636.         Vec3 up(mat.GetColumn(2));
  637.         float spreadHoriz(0), spreadVert(0);
  638.  
  639.         while (--trysLimit >= 0)
  640.         {
  641.                 //miss randomly on left/right
  642.                 spreadHoriz = cry_random(0.9f, 1.2f) * (cry_random(0, 99) < 50 ? -1.0f : 1.0f);
  643.                 //miss randomly on up/dowm - only in 3D
  644.                 //              spreadVert = cry_random(1.2f, 1.5f) * (cry_random(0, 99)<50 ? -1.0f : 1.0f);
  645.                 //miss randomly on up/dowm
  646.                 spreadVert = cry_random(0.0f, 1.5f) * (cry_random(0, 99) < 50 ? -1.0f : .35f);
  647.                 Vec3 candidateShootPos(vTargetPos + spreadHoriz * right + spreadVert * up);
  648.                 if (m_pFireCmdHandler->ValidateFireDirection(candidateShootPos - GetFirePos(), false))
  649.                         return candidateShootPos;
  650.         }
  651.         // can't find any good point to miss
  652.         return ZERO;
  653. }
  654.  
  655. //
  656. //----------------------------------------------------------------------------------------------------
  657. bool CPuppet::CheckAndGetFireTarget_Deprecated(IAIObject* pTarget, bool lowDamage, Vec3& vTargetPos, Vec3& vTargetDir) const
  658. {
  659.         //              CAIObject* pTargetAI = static_cast<CAIObject*>(pTarget);
  660.  
  661.         if (!m_pFireCmdHandler)
  662.                 return false;
  663.  
  664.         CAIActor* pTargetActor = pTarget->CastToCAIActor();
  665.         DamagePartVector* pDamageParts = pTargetActor ? pTargetActor->GetDamageParts() : NULL;
  666.         if (pDamageParts)
  667.         {
  668.                 DamagePartVector& parts = *(pDamageParts);
  669.                 std::vector<float> weights;
  670.                 std::vector<int> partLut;
  671.  
  672.                 // Check if the parts have multipliers set up.
  673.                 float accMult = 0.0f;
  674.                 int n = (int)parts.size();
  675.                 for (int i = 0; i < n; ++i)
  676.                         accMult += parts[i].damageMult;
  677.  
  678.                 weights.resize(n);
  679.  
  680.                 if (accMult > 0.001f)
  681.                 {
  682.                         // Sort based on damage multiplier.
  683.                         // Add slight random scaling to randomize selection of objects of same multiplier.
  684.                         for (int i = 0; i < n; ++i)
  685.                         {
  686.                                 weights[i] = parts[i].damageMult * cry_random(1.0f, 1.01f);
  687.                                 if (lowDamage && parts[i].damageMult > 0.95f) continue;
  688.                                 partLut.push_back(i);
  689.                         }
  690.                 }
  691.                 else
  692.                 {
  693.                         // Sort based on part volume.
  694.                         // Add slight random scaling to randomize selection of objects of same multiplier.
  695.                         for (int i = 0; i < n; ++i)
  696.                         {
  697.                                 // Sort from smallest volume to largest, hence negative sign.
  698.                                 weights[i] = -parts[i].volume * cry_random(1.0f, 1.01f);
  699.                                 partLut.push_back(i);
  700.                         }
  701.                 }
  702.  
  703.                 std::sort(partLut.begin(), partLut.end(), SDamageLUTSorter(weights));
  704.  
  705.                 for (std::vector<int>::iterator it = partLut.begin(); it != partLut.end(); ++it)
  706.                 {
  707.                         vTargetPos = parts[*it].pos;
  708.                         vTargetDir = vTargetPos - GetFirePos();
  709.                         if (m_pFireCmdHandler->ValidateFireDirection(vTargetDir, true))
  710.                                 return true;
  711.                 }
  712.         }
  713.         else
  714.         {
  715.                 // Inanimate target, use the default position.
  716.                 vTargetPos = pTarget->GetPos();
  717.                 vTargetDir = vTargetPos - GetFirePos();
  718.  
  719.                 // The head is accessible.
  720.                 if (m_pFireCmdHandler->ValidateFireDirection(vTargetDir, false))
  721.                         return true;
  722.         }
  723.  
  724.         // TODO: Should probably use one of those missed points instead, since they cannot reach the target anyway.
  725.         vTargetPos = ChooseMissPoint_Deprecated(vTargetPos);
  726.  
  727.         return true;
  728. }
  729.  
downloadPuppetPhys.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