BVB Source Codes

CRYENGINE Show AIVehicle.cpp Source code

Return Download CRYENGINE: download AIVehicle.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "AIVehicle.h"
  5.  
  6. #include "GoalOp.h"
  7. #include <CryPhysics/IPhysics.h>
  8. #include <CrySystem/ISystem.h>
  9.  
  10. #include <CrySystem/IConsole.h>
  11. #include "VertexList.h"
  12. #include <vector>
  13. #include <algorithm>
  14. #include <CryMath/Cry_Vector2.h>
  15.  
  16. #include <CryNetwork/ISerialize.h>
  17.  
  18. CAIVehicle::CAIVehicle() :
  19.         m_bDriverInside(false),
  20.         m_driverInsideCheck(-1),
  21.         m_playerInsideCheck(-1),
  22.         m_fNextFiringTime(GetAISystem()->GetFrameStartTime()),
  23.         m_fFiringStartTime(GetAISystem()->GetFrameStartTime()),
  24.         m_fFiringPauseTime(GetAISystem()->GetFrameStartTime()),
  25.         m_bPoweredUp(false),
  26.         m_ShootPhase(0),
  27.         m_vDeltaTarget(ZERO)
  28. {
  29.         _fastcast_CAIVehicle = true;
  30.         // can't reset now - no parameters are initialized yet
  31.         //      Reset();
  32.  
  33. }
  34.  
  35. //
  36. //---------------------------------------------------------------------------------------------------------
  37. CAIVehicle::~CAIVehicle(void)
  38. {
  39.  
  40. }
  41.  
  42. //
  43. //---------------------------------------------------------------------------------------------------------
  44. void CAIVehicle::UpdateDisabled(EObjectUpdate type)
  45. {
  46.         CAIActor::UpdateDisabled(type);
  47.         m_bDryUpdate = type == AIUPDATE_DRY;
  48.         AlertPuppets();
  49.         m_driverInsideCheck = -1;
  50.         m_playerInsideCheck = -1;
  51. }
  52.  
  53. //
  54. //---------------------------------------------------------------------------------------------------------
  55. void CAIVehicle::Update(EObjectUpdate type)
  56. {
  57.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  58.         CCCPOINT(CAIVehicle_Update);
  59.  
  60.         m_driverInsideCheck = -1;
  61.         m_playerInsideCheck = -1;
  62.  
  63.         const SAIBodyInfo& bodyInfo = QueryBodyInfo();
  64.  
  65.         UpdateBehaviorSelectionTree();
  66.  
  67.         m_bDryUpdate = type == AIUPDATE_DRY;
  68.  
  69.         // make sure to update direction when entity is not moved
  70.         SetPos(bodyInfo.vEyePos);
  71.         SetBodyDir(bodyInfo.GetBodyDir());
  72.         SetEntityDir(bodyInfo.vEntityDir);
  73.         SetMoveDir(bodyInfo.vMoveDir);
  74.  
  75.         static bool doDryUpdateCall = true;
  76.         AlertPuppets();
  77.  
  78.         UpdateHealthTracking();
  79.         m_damagePartsUpdated = false;
  80.  
  81.         if (!m_bDryUpdate)
  82.         {
  83.                 FRAME_PROFILER("AI system vehicle full update", gEnv->pSystem, PROFILE_AI);
  84.  
  85.                 CTimeValue fCurrentTime = GetAISystem()->GetFrameStartTime();
  86.                 if (m_fLastUpdateTime.GetSeconds() > 0.0f)
  87.                         m_fTimePassed = min(0.5f, (fCurrentTime - m_fLastUpdateTime).GetSeconds());
  88.                 else
  89.                         m_fTimePassed = 0;
  90.  
  91.                 m_fLastUpdateTime = fCurrentTime;
  92.  
  93.                 m_State.Reset();
  94.  
  95.                 GetStateFromActiveGoals(m_State);
  96.  
  97.                 UpdatePuppetInternalState();
  98.         }
  99.         else if (doDryUpdateCall)
  100.         {
  101.                 // if approaching then always update
  102.                 for (size_t i = 0; i < m_vActiveGoals.size(); i++)
  103.                 {
  104.                         QGoal& Goal = m_vActiveGoals[i];
  105.                         Goal.pGoalOp->ExecuteDry(this);
  106.                 }
  107.         }
  108.  
  109.         //--------------------------------------------------------
  110.         // Orient towards the attention target always
  111.         CAIObject* pAttentionTarget = m_refAttentionTarget.GetAIObject();
  112.  
  113.         Navigate(pAttentionTarget);
  114.  
  115.         // ---------- update proxy object
  116.         if (pAttentionTarget)
  117.         {
  118.                 m_State.nTargetType = pAttentionTarget->GetType();
  119.                 m_State.bTargetEnabled = pAttentionTarget->IsEnabled();
  120.         }
  121.         else
  122.         {
  123.                 m_State.nTargetType = -1;
  124.                 m_State.bTargetEnabled = false;
  125.         }
  126.  
  127.         FireCommand();
  128.  
  129.         m_vLastMoveDir = m_State.vMoveDir;
  130.         if (gAIEnv.CVars.UpdateProxy)
  131.         {
  132.                 GetProxy()->Update(m_State, !m_bDryUpdate);
  133.                 UpdateAlertness();
  134.         }
  135. }
  136.  
  137. float CAIVehicle::RecalculateAccuracy(void)
  138. {
  139.  
  140.         float fAccuracy = m_Parameters.m_fAccuracy;
  141.  
  142.         if (fAccuracy > 1.f)
  143.                 fAccuracy = 1.f;
  144.         else if (fAccuracy < 0)
  145.                 fAccuracy = 0;
  146.  
  147.         return fAccuracy;
  148.  
  149. }
  150. Vec3 CAIVehicle::PredictMovingTarget(const CAIObject* pTarget, const Vec3& vTargetPos, const Vec3& vFirePos, const float duration, const float distpred)
  151. {
  152.         Vec3 vError(ZERO);
  153.  
  154.         // if we need a prediction of the target
  155.         if (pTarget)
  156.         {
  157.                 pe_status_dynamics dSt;
  158.                 GetProxy()->GetPhysics()->GetStatus(&dSt);
  159.                 IPhysicalEntity* pPhys = pTarget->GetPhysics();
  160.                 if (pPhys)
  161.                 {
  162.                         pPhys->GetStatus(&dSt);
  163.                         if (GetSubType() == CAIObject::STP_HELI)
  164.                         {
  165.                                 vError = dSt.v * duration;
  166.                         }
  167.                         else
  168.                         {
  169.                                 Vec3 vPrediction = vTargetPos + dSt.v * duration;
  170.                                 Vec3 vTmp = vPrediction - vFirePos;
  171.                                 if (distpred > 0.0f)
  172.                                 {
  173.                                         float len = vTmp.GetLength();
  174.                                         vError.z = len / distpred;
  175.                                 }
  176.                         }
  177.  
  178.                 }
  179.         }
  180.         return vError;
  181. }
  182.  
  183. Vec3 CAIVehicle::GetError(const Vec3& vTargetPos, const Vec3& vFirePos, const float fAccuracy)
  184. {
  185.         //      add an error to the target position depending on accuracy
  186.         Vec3 vError(ZERO);
  187.  
  188.         if (fAccuracy < 1.0f)
  189.         {
  190.                 float dist = (vTargetPos - vFirePos).GetLength();
  191.                 float fAccuracyScale = (1.0f - fAccuracy);
  192.                 float rangeRotation = fAccuracyScale * cry_random(-50.0f, 50.0f);
  193.                 float zofs = dist * sinf(DEG2RAD(0.0f));
  194.  
  195.                 float rangeLength;
  196.                 if (cry_random(0.0f, 0.99f) < fAccuracy)
  197.                         rangeLength = fAccuracyScale * cry_random(0.0f, 27.0f);
  198.                 else
  199.                         rangeLength = fAccuracyScale * cry_random(15.0f, 25.0f);
  200.  
  201.                 vError = vFirePos - vTargetPos;
  202.                 vError.z = 0.0f;
  203.                 vError.NormalizeSafe();
  204.                 vError *= rangeLength;
  205.                 vError *= min(1.5f, dist / 100.0f);
  206.  
  207.                 Matrix33 rotmatZ = Matrix33::CreateRotationZ(DEG2RAD(rangeRotation));
  208.                 vError = rotmatZ * vError;
  209.  
  210.                 vError = vError + vTargetPos;
  211.                 vError.z = gEnv->p3DEngine->GetTerrainElevation(vError.x, vError.y);
  212.                 vError = vError - vTargetPos;
  213.                 vError.z -= zofs;
  214.         }
  215.  
  216.         return vError;
  217.  
  218. }
  219.  
  220. bool CAIVehicle::CheckExplosion(const Vec3& vTargetPos, const Vec3& vFirePos, const Vec3& vActuallFireDir, const float fDamageRadius)
  221. {
  222.         // get the hit point of a bullet, then check if there is a friend around the hit point.
  223.         // not to give a damage to same species.
  224.  
  225.         const Vec3 vDirVector = vTargetPos - vFirePos;
  226.         float fDamageRadius2 = fDamageRadius > 0.f ? fDamageRadius * fDamageRadius : 1.0f;
  227.  
  228.         Vec3 vHitPoint;
  229.  
  230.         PhysSkipList skipList;
  231.         GetPhysicalSkipEntities(skipList);
  232.  
  233.         ray_hit hit;
  234.  
  235.         if (gAIEnv.pWorld->RayWorldIntersection(
  236.               vFirePos, vDirVector, COVER_OBJECT_TYPES,
  237.               AI_VISION_RAY_CAST_FLAG_BLOCKED_BY_SOLID_COVER,
  238.               &hit, 1, &skipList[0], skipList.size()))
  239.         {
  240.                 //When the bullet will hit a object which is on the way.
  241.                 vHitPoint = hit.pt;
  242.         }
  243.         else
  244.         {
  245.                 //When the bullet will hit the player.
  246.                 vHitPoint = vTargetPos;
  247.         }
  248.  
  249.         CAIObject* pTarget = 0;
  250.         bool bNoFriendsInRadius = GetEnemyTarget(AIOBJECT_ACTOR, vHitPoint, fDamageRadius2, &pTarget);
  251.         if (bNoFriendsInRadius && !pTarget)
  252.                 bNoFriendsInRadius = GetEnemyTarget(AIOBJECT_PLAYER, vHitPoint, fDamageRadius2, &pTarget);
  253.         if (bNoFriendsInRadius && !pTarget)
  254.                 bNoFriendsInRadius = GetEnemyTarget(AIOBJECT_VEHICLE, vHitPoint, fDamageRadius2, &pTarget);
  255.  
  256.         Vec3 vActualDir = vActuallFireDir;
  257.         vActualDir.SetLength(vDirVector.GetLength());
  258.  
  259.         if (GetSubType() != CAIObject::STP_HELI)
  260.         {
  261.                 // if will hit the terrain/static and there is no friend
  262.                 if (bNoFriendsInRadius == true)
  263.                 {
  264.                         if (gAIEnv.pWorld->RayWorldIntersection(
  265.                               vFirePos, vActualDir, COVER_OBJECT_TYPES,
  266.                               AI_VISION_RAY_CAST_FLAG_BLOCKED_BY_SOLID_COVER,
  267.                               &hit, 1, &skipList[0], skipList.size()))
  268.                         {
  269.                                 // and if it is far away from the target.
  270.                                 if ((vTargetPos - hit.pt).GetLength() > fDamageRadius * 3.0f)
  271.                                         // shouldn't fire
  272.                                         bNoFriendsInRadius = false;
  273.  
  274.                         }
  275.                 }
  276.         }
  277.         else
  278.         {
  279.                 if (bNoFriendsInRadius == true)
  280.                 {
  281.                         if (gAIEnv.pWorld->RayWorldIntersection(
  282.                               vFirePos, vActualDir, COVER_OBJECT_TYPES,
  283.                               AI_VISION_RAY_CAST_FLAG_BLOCKED_BY_SOLID_COVER,
  284.                               &hit, 1, &skipList[0], skipList.size()))
  285.                         {
  286.                                 if ((vFirePos - hit.pt).GetLength() < fDamageRadius * 10.0f)
  287.                                         bNoFriendsInRadius = false;
  288.                         }
  289.                 }
  290.         }
  291.  
  292.         return bNoFriendsInRadius;
  293.  
  294. }
  295.  
  296. // decides whether fire or not
  297. void CAIVehicle::FireCommand(void)
  298. {
  299.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  300.  
  301.         // basic filters
  302.  
  303.         m_State.fire = eAIFS_Off;
  304.         m_State.aimTargetIsValid = false; //vAimTargetPos.Set(0,0,0);
  305.  
  306.         if (!AllowedToFire())
  307.         {
  308.                 m_ShootPhase = 0;
  309.                 m_fFiringStartTime = GetAISystem()->GetFrameStartTime();
  310.                 return;
  311.         }
  312.  
  313.         CAIObject* pFireTarget = GetFireTargetObject();
  314.  
  315.         if (!pFireTarget)
  316.                 return;
  317.  
  318.         if (!GetProxy())
  319.                 return;
  320.  
  321.         // basic paramaters
  322.         // m_CurrentWeaponDescriptor is not correct now these paramters below should be given by Descriptor
  323.         // 4/8/2006 Tetsuji
  324.  
  325.         bool bCoaxial = (m_fireMode == FIREMODE_SECONDARY);
  326.         bool bAAA = (m_fireMode == FIREMODE_CONTINUOUS && GetSubType() == CAIObject::STP_CAR);
  327.         float fDamageRadius = bCoaxial ? 0.5f : 15.0f;
  328.         float fAccuracy = RecalculateAccuracy();
  329.  
  330.         const SAIBodyInfo& bodyInfo = GetBodyInfo();
  331.  
  332.         Vec3 vActualFireDir = bodyInfo.vFireDir;
  333.         Vec3 vFirePos = bodyInfo.vFirePos;
  334.         Vec3 vFwdDir = bodyInfo.vMoveDir;
  335.         Vec3 vMyPos = bodyInfo.vEyePos;
  336.  
  337.         if (GetEntity())
  338.         {
  339.                 Matrix33 worldRotMat(GetEntity()->GetWorldTM());
  340.                 Vec3 vFwdOrg(0.0f, 1.0f, 0.0f);
  341.                 vFwdDir = worldRotMat * vFwdOrg;
  342.                 //              gEnv->pAISystem->AddDebugLine( vFirePos, vFirePos + vFwdDir * 20.0f , 255, 255, 255, 1.0f);
  343.         }
  344.  
  345.         IPhysicalEntity* pPhys = GetPhysics();
  346.         if (pPhys)
  347.         {
  348.                 pe_status_pos my_status;
  349.                 pPhys->GetStatus(&my_status);
  350.                 vMyPos = my_status.pos;
  351.         }
  352.  
  353.         Vec3 vTargetPos;
  354.         {
  355.                 IPhysicalEntity* pAttPhys = pFireTarget->GetPhysics();
  356.                 if (pAttPhys)
  357.                 {
  358.                         pe_status_pos target_status;
  359.                         pAttPhys->GetStatus(&target_status);
  360.                         vTargetPos = target_status.pos;
  361.                         Vec3 ofs = target_status.BBox[0] + target_status.BBox[1];
  362.                         ofs.x *= 0.5f;
  363.                         ofs.y *= 0.5f;
  364.                         ofs.z *= 0.25f;
  365.                         vTargetPos += ofs;
  366.                 }
  367.                 else
  368.                 {
  369.                         vTargetPos = pFireTarget->GetPos();
  370.                 }
  371.         }
  372.  
  373.         float targetHeight = vTargetPos.z - gEnv->p3DEngine->GetTerrainElevation(vTargetPos.x, vTargetPos.y);
  374.         float fireHeight = vFirePos.z - gEnv->p3DEngine->GetTerrainElevation(vFirePos.x, vFirePos.y);
  375.  
  376.         // For the helicopter/vtol missiles
  377.         if (GetSubType() == CAIObject::STP_HELI)
  378.         {
  379.  
  380.                 if (m_ShootPhase == 0)
  381.                 {
  382.                         fDamageRadius = 2.0f;
  383.                         m_vDeltaTarget = GetError(vTargetPos, vFirePos, fAccuracy);
  384.                         m_vDeltaTarget += PredictMovingTarget(pFireTarget, vTargetPos, vFirePos, 1.0f, 0.0f);
  385.                         m_vDeltaTarget += vTargetPos;
  386.  
  387.                         Vec3 vTargetDir = m_vDeltaTarget - vFirePos;
  388.                         Vec3 vUnitTargetDir = vTargetDir;
  389.                         Vec3 vNormalizedTargetDir = vTargetDir;
  390.  
  391.                         vNormalizedTargetDir.NormalizeSafe();
  392.                         float distanceToTheTarget = vTargetDir.GetLength();
  393.                         // If the target is not in front of him. can't fire.
  394.  
  395.                         vUnitTargetDir.NormalizeSafe();
  396.                         //                      gEnv->pAISystem->AddDebugLine( vFirePos, vFirePos + vUnitTargetDir * 20.0f , 255, 0, 0, 1.0f);
  397.  
  398.                         float fDifference = vUnitTargetDir.Dot(vFwdDir);
  399.                         if (fDifference < cos_tpl(DEG2RAD(30.0f)))
  400.                         {
  401.                                 m_fFiringStartTime = GetAISystem()->GetFrameStartTime();
  402.                                 return;
  403.                         }
  404.                         // if a missile pass by near a target
  405.                         Vec3 vTmp = vFwdDir.Cross(vTargetDir);
  406.  
  407.                         float d = vTmp.GetLength();
  408.                         float dot = vNormalizedTargetDir.Dot(vFwdDir);
  409.  
  410.                         if (d > 12.0f || (dot > DEG2RAD(10.0f) && d > 10.0f))
  411.                         {
  412.                                 m_fFiringStartTime = GetAISystem()->GetFrameStartTime();
  413.                                 return;
  414.                         }
  415.  
  416.                         // it also need to be vertical to a wing vector.
  417.                         // this check is needed because firing position is not accurate.26/06/2006 tetsuji
  418.                         // check if there is the same specie around a target position
  419.  
  420.                         if (m_fireMode != FIREMODE_FORCED)
  421.                         {
  422.                                 if (CheckExplosion(m_vDeltaTarget, vFirePos, vUnitTargetDir, fDamageRadius) == false)
  423.                                 {
  424.                                         m_fFiringStartTime = GetAISystem()->GetFrameStartTime();
  425.                                         return;
  426.                                 }
  427.                                 else
  428.                                 {
  429.                                         m_ShootPhase = 1;
  430.                                 }
  431.                         }
  432.                         else
  433.                                 m_ShootPhase = 1;
  434.  
  435.                 }
  436.                 if (m_ShootPhase)
  437.                 {
  438.                         // finalize a result and check the time.
  439.                         CTimeValue firingDuration;
  440.  
  441.                         firingDuration.SetSeconds(0.0f);
  442.                         firingDuration += m_fFiringStartTime;
  443.                         if (GetAISystem()->GetFrameStartTime() < firingDuration)
  444.                         {
  445.                                 return;
  446.                         }
  447.  
  448.                         m_State.vLookTargetPos = m_vDeltaTarget;
  449.                         m_State.vShootTargetPos = m_vDeltaTarget;
  450.                         m_State.vAimTargetPos = m_vDeltaTarget;
  451.                         m_State.aimTargetIsValid = true;
  452.                         m_State.fire = eAIFS_On;
  453.                         m_ShootPhase = 0;
  454.  
  455.                 }
  456.                 return;
  457.         }
  458.  
  459.         // For the warrior,
  460.         if (fireHeight > 10.0f)
  461.         {
  462.  
  463.                 if (GetAISystem()->GetFrameStartTime() < m_fNextFiringTime)
  464.                 {
  465.                         m_State.fire = eAIFS_On;
  466.                 }
  467.                 else
  468.                 {
  469.                         m_State.vLookTargetPos = vTargetPos;
  470.                         m_State.vAimTargetPos = vTargetPos;
  471.                         m_State.aimTargetIsValid = true;
  472.                         m_State.vShootTargetPos = vTargetPos;
  473.                         m_State.fire = eAIFS_On;
  474.                         CTimeValue firingDuration;
  475.                         firingDuration.SetSeconds(3.0f);
  476.                         firingDuration += m_fFiringStartTime;
  477.                         m_fNextFiringTime = firingDuration;
  478.                 }
  479.  
  480.                 return;
  481.         }
  482.  
  483.         // For tank Coaxial Gun
  484.         if (bCoaxial == true || bAAA == true)
  485.         {
  486.  
  487.                 Vec3 vTargetDir = vTargetPos - vFirePos;
  488.                 //After the rotation of the tunnet has been completed,
  489.                 float fDuration = 2.0f;
  490.                 float fBoxRange = 3.0f;
  491.                 float fMaxDot = 30.0f;
  492.                 if (bAAA == true)
  493.                 {
  494.                         fDuration = 2.0f;
  495.                         fBoxRange = 30.0f;
  496.                         fMaxDot = 30.0f;
  497.                         PredictMovingTarget(pFireTarget, vTargetPos, vFirePos, 1.0f, 30.0f);
  498.                         if (vTargetDir.GetLength() < 20.0f)
  499.                         {
  500.                                 m_State.vLookTargetPos = vTargetPos;
  501.                                 m_State.vAimTargetPos = vTargetPos;
  502.                                 m_State.aimTargetIsValid = true;
  503.                                 m_State.vShootTargetPos = vTargetPos;
  504.                                 return;
  505.                         }
  506.                 }
  507.                 else
  508.                 {
  509.  
  510.                         Vec3 vTargetDirFromCenter = vTargetPos - vMyPos;
  511.                         Vec3 vTargetDirFromFirePos = vTargetPos - vFirePos;
  512.                         Vec3 vCenterToFirePos = vFirePos - vMyPos;
  513.                         vTargetDirFromCenter.z = vTargetDirFromFirePos.z = vCenterToFirePos.z = 0.0f;
  514.                         float distanceFromCenter = vTargetDirFromCenter.GetLength();
  515.                         float distanceFromFirePos = vTargetDirFromFirePos.GetLength();
  516.                         float distanceFromCenterToFire = vCenterToFirePos.GetLength();
  517.                         fDuration = 4.0f;
  518.                         fBoxRange = 5.0f;
  519.                         fMaxDot = (distanceFromCenter < 15.0f) ? 120.0f : 15.0f;
  520.                         if (distanceFromCenter < distanceFromCenterToFire + 1.5f)
  521.                         {
  522.                                 return;
  523.                         }
  524.                 }
  525.  
  526.                 Vec3 vTmp = vActualFireDir.Cross(vTargetDir);
  527.                 float d = vTmp.GetLength();
  528.  
  529.                 vTargetDir.NormalizeSafe();
  530.                 float inner = vActualFireDir.Dot(vTargetDir);
  531.  
  532.                 bool allowFiring = true;
  533.  
  534.                 //if there is still a big difference between acutal fire direction and ideal fire direction,
  535.                 if (d > fBoxRange || inner < cos_tpl(DEG2RAD(fMaxDot)) || GetAISystem()->GetFrameStartTime() >= m_fNextFiringTime)
  536.                 {
  537.                         m_fNextFiringTime.SetSeconds(fDuration);
  538.                         m_fNextFiringTime += GetAISystem()->GetFrameStartTime();
  539.  
  540.                         m_State.vLookTargetPos = vTargetPos;
  541.                         m_State.vAimTargetPos = vTargetPos;
  542.                         m_State.aimTargetIsValid = true;
  543.                         m_State.vShootTargetPos = vTargetPos;
  544.                         allowFiring = false;
  545.                 }
  546.                 else
  547.                 {
  548.                         if (bAAA != true)
  549.                         {
  550.                                 vTargetPos = pFireTarget->GetPos();
  551.                                 vTargetDir = vTargetPos - vFirePos;
  552.                                 vTargetPos.z -= 0.3f;
  553.                                 m_State.vLookTargetPos = vTargetPos;
  554.                                 m_State.vAimTargetPos = vTargetPos;
  555.                                 m_State.aimTargetIsValid = true;
  556.                                 m_State.vShootTargetPos = vTargetPos;
  557.                         }
  558.                 }
  559.  
  560.                 UpdateTargetTracking(GetWeakRef(pFireTarget), m_State.vAimTargetPos);
  561.  
  562.                 if (allowFiring && GetAISystem()->GetFrameStartTime() < m_fNextFiringTime)
  563.                 {
  564.                         if (AdjustFireTarget(pFireTarget, m_State.vShootTargetPos, CanDamageTarget(), 0.5f,
  565.                                              DEG2RAD(30.0f), &m_State.vShootTargetPos))
  566.                                 m_State.fire = eAIFS_On;
  567.                 }
  568.  
  569.                 return;
  570.         }
  571.  
  572.         // For the tank cannon
  573.         // in this part, we wait until the turret is moving then shoot
  574.         {
  575.  
  576.                 if (m_ShootPhase == 0)      //aiming set up
  577.                 {
  578.                         if (targetHeight < 10.0f)
  579.                         {
  580.                                 IPhysicalEntity* pAttPhys = pFireTarget->GetPhysics();
  581.                                 if (pAttPhys)
  582.                                 {
  583.                                         pe_status_dynamics dSt;
  584.                                         pAttPhys->GetStatus(&dSt);
  585.                                 }
  586.  
  587.                                 m_vDeltaTarget = GetError(vTargetPos, vFirePos, fAccuracy);
  588.                                 m_vDeltaTarget += PredictMovingTarget(pFireTarget, vTargetPos, vFirePos, 1.0f, 0.0f);
  589.                                 m_vDeltaTarget += vTargetPos;
  590.  
  591.                         }
  592.                         m_ShootPhase++;
  593.  
  594.                         CTimeValue tValue;
  595.                         tValue.SetSeconds(5.0f);
  596.                         m_fFiringPauseTime = GetAISystem()->GetFrameStartTime() + tValue;
  597.  
  598.                 }
  599.                 else if (m_ShootPhase == 1)     //aiming ( the turret is rotating )
  600.                 {
  601.                         m_State.vLookTargetPos = m_State.vAimTargetPos = m_State.vShootTargetPos = m_vDeltaTarget;
  602.  
  603.                         //After the rotation of the tunnet has been completed,
  604.                         Vec3 vTargetDir = m_vDeltaTarget - vFirePos;
  605.  
  606.                         vTargetDir.NormalizeSafe();
  607.                         vActualFireDir.NormalizeSafe();
  608.  
  609.                         float inner = vActualFireDir.Dot(vTargetDir);
  610.                         float cosval = cos_tpl(DEG2RAD(3.0f));
  611.                         if (inner > cosval || m_fFiringPauseTime < GetAISystem()->GetFrameStartTime())
  612.                         {
  613.                                 CTimeValue tValue;
  614.                                 tValue.SetSeconds(0.5f);
  615.                                 m_fFiringPauseTime = GetAISystem()->GetFrameStartTime() + tValue;
  616.                                 m_ShootPhase++;
  617.                         }
  618.                 }
  619.                 else if (m_ShootPhase == 2)      //fire ( the turret is fixed )
  620.                 {
  621.                         m_State.vLookTargetPos = m_State.vAimTargetPos = m_State.vShootTargetPos = m_vDeltaTarget;
  622.                         if (m_fFiringPauseTime < GetAISystem()->GetFrameStartTime())
  623.                         {
  624.                                 CTimeValue tValue;
  625.                                 tValue.SetSeconds(0.5f);
  626.                                 m_fFiringPauseTime = GetAISystem()->GetFrameStartTime() + tValue;
  627.                                 m_ShootPhase++;
  628.                         }
  629.  
  630.                 }
  631.                 else if (m_ShootPhase == 3)      //fire ( the turret is fixed )
  632.                 {
  633.                         m_State.vLookTargetPos = m_State.vAimTargetPos = m_State.vShootTargetPos = vActualFireDir * 10.0f + vFirePos; //fix the turret
  634.  
  635.                         CTimeValue tValue;
  636.                         tValue.SetSeconds(3.0f);
  637.  
  638.                         if (m_fFiringPauseTime < GetAISystem()->GetFrameStartTime())
  639.                         {
  640.                                 if (CheckTargetInRange(m_vDeltaTarget) && m_fFiringPauseTime + tValue > GetAISystem()->GetFrameStartTime())
  641.                                 {
  642.                                         Vec3 vTargetDir = m_vDeltaTarget - vFirePos;
  643.                                         Vec3 vTmp = vActualFireDir.Cross(vTargetDir);
  644.                                         float d = vTmp.GetLength();
  645.                                         float distanceToTheTarget = vTargetDir.GetLength();
  646.                                         vTargetDir.NormalizeSafe();
  647.                                         float inner = vActualFireDir.Dot(vTargetDir);
  648.  
  649.                                         if (d < 30.0f && inner > cos_tpl(DEG2RAD(30.0f)))
  650.                                         {
  651.                                                 if (m_fireMode == FIREMODE_FORCED || CheckExplosion(vActualFireDir * distanceToTheTarget + vFirePos, vFirePos, vActualFireDir, fDamageRadius) == true)
  652.                                                 {
  653.                                                         m_State.fire = eAIFS_On;
  654.                                                         return;
  655.                                                 }
  656.  
  657.                                         }
  658.                                         else
  659.                                         {
  660.                                                 tValue.SetSeconds(3.0f);
  661.                                         }
  662.                                 }
  663.                                 else
  664.                                 {
  665.                                         m_ShootPhase = 0;
  666.                                 }
  667.  
  668.                         }
  669.  
  670.                 }
  671.         }
  672. }
  673.  
  674. //
  675. //---------------------------------------------------------------------------------------------------------
  676. void CAIVehicle::ParseParameters(const AIObjectParams& params, bool bParseMovementParams)
  677. {
  678.         CPuppet::ParseParameters(params, bParseMovementParams);   // calls also CAIActor.ParseParams
  679.  
  680.         m_Parameters = params.m_sParamStruct;
  681. }
  682.  
  683. //
  684. //---------------------------------------------------------------------------------------------------------
  685. EntityId CAIVehicle::GetPerceivedEntityID() const
  686. {
  687.         // Use the driver if one is present
  688.         EntityId driverId = GetDriverEntity();
  689.         if (driverId != 0)
  690.                 return driverId;
  691.  
  692.         return CPuppet::GetPerceivedEntityID();
  693. }
  694.  
  695. //
  696. //---------------------------------------------------------------------------------------------------------
  697. //
  698. void CAIVehicle::Reset(EObjectResetType type)
  699. {
  700.         CPuppet::Reset(type);
  701.  
  702.         if (type == AIOBJRESET_INIT)
  703.                 SetObserver(false); // TODO(M谩rcio): clean this up
  704.  
  705.         CAISystem* pAISystem = GetAISystem();
  706.  
  707.         m_fNextFiringTime = pAISystem->GetFrameStartTime();
  708.         m_fFiringStartTime = pAISystem->GetFrameStartTime();
  709.         m_fFiringPauseTime = pAISystem->GetFrameStartTime();
  710.         m_bPoweredUp = false;
  711.         m_ShootPhase = 0;
  712.  
  713.         m_bDriverInside = false;
  714.         m_vDeltaTarget.zero();
  715. }
  716.  
  717. //
  718. //---------------------------------------------------------------------------------------------------------
  719. //
  720. void CAIVehicle::Event(unsigned short eType, SAIEVENT* pEvent)
  721. {
  722.         CAISystem* pAISystem = GetAISystem();
  723.         switch (eType)
  724.         {
  725.         case AIEVENT_AGENTDIED:
  726.                 m_bEnabled = false;
  727.                 pAISystem->NotifyEnableState(this, m_bEnabled);
  728.                 pAISystem->UpdateGroupStatus(GetGroupId());
  729.  
  730.                 //SetObserver(false);
  731.                 OnDriverChanged(false);
  732.  
  733.                 m_State.ClearSignals();
  734.  
  735.                 break;
  736.         case AIEVENT_DRIVER_IN:
  737.         case AIEVENT_DRIVER_OUT:
  738.                 {
  739.                         const bool bEntered = (eType == AIEVENT_DRIVER_IN);
  740.                         OnDriverChanged(bEntered);
  741.                         if (pEvent && pEvent->bSetObserver)
  742.                         {
  743.                                 SetObserver(bEntered);
  744.                         }
  745.                 }
  746.                 return;     // those are vehicle specific, don't pass it to puppet
  747.         case AIEVENT_DISABLE:
  748.                 m_bEnabled = false;
  749.                 pAISystem->NotifyEnableState(this, m_bEnabled);
  750.                 pAISystem->UpdateGroupStatus(GetGroupId());
  751.  
  752.                 //SetObserver(false);
  753.  
  754.                 OnDriverChanged(false);
  755.                 return;
  756.                 break;
  757.         // can not just enable vehicles - it has to have driver in
  758.         case AIEVENT_ENABLE:
  759.                 if (m_bDriverInside)
  760.                         Event(AIEVENT_DRIVER_IN, pEvent);
  761.  
  762.                 //SetObserver(true);
  763.                 OnDriverChanged(m_bDriverInside);
  764.                 return;
  765.                 break;
  766.         default:
  767.                 break;
  768.         }
  769.  
  770.         CPuppet::Event(eType, pEvent);
  771. }
  772.  
  773. //
  774. //---------------------------------------------------------------------------------------------------------
  775. void CAIVehicle::OnDriverChanged(bool bEntered)
  776. {
  777.         CAISystem* pAISystem = GetAISystem();
  778.         assert(pAISystem);
  779.  
  780.         m_bDriverInside = bEntered;
  781.         m_bEnabled = bEntered;
  782.  
  783.         pAISystem->NotifyEnableState(this, m_bEnabled);
  784.         pAISystem->UpdateGroupStatus(GetGroupId());
  785.  
  786.         // TODO This was called before when receiving the AIEVENT_DRIVER_OUT event. Check if this
  787.         // needs to be executed still. I suspect not. (Kevin)
  788.         /*if (!bEntered)
  789.            {
  790.            gAIEnv.pAIObjectManager->RemoveObjectFromAllOfType(AIOBJECT_ACTOR,this);
  791.            gAIEnv.pAIObjectManager->RemoveObjectFromAllOfType(AIOBJECT_VEHICLE,this);
  792.            gAIEnv.pAIObjectManager->RemoveObjectFromAllOfType(AIOBJECT_ATTRIBUTE,this);
  793.            }*/
  794. }
  795.  
  796. //
  797. //---------------------------------------------------------------------------------------------------------
  798. void CAIVehicle::Navigate(CAIObject* pTarget)
  799. {
  800.         CCCPOINT(CAIVehicle_Navigate);
  801.  
  802.         m_State.vForcedNavigation = m_vForcedNavigation;
  803.         m_State.fForcedNavigationSpeed = m_fForcedNavigationSpeed;
  804.  
  805.         if (m_bLooseAttention)
  806.         {
  807.                 CAIObject* pLooseAttentionTarget = m_refLooseAttentionTarget.GetAIObject();
  808.                 if (pLooseAttentionTarget)
  809.                         pTarget = pLooseAttentionTarget;
  810.                 else
  811.                         pTarget = NULL;
  812.         }
  813.  
  814.         Vec3 vDir, vTargetPos;
  815.         float fTime = GetAISystem()->GetFrameDeltaTime();
  816.         //      int TargetType = AIOBJECT_NONE;
  817.  
  818.         if (pTarget)
  819.         {
  820.                 const SAIBodyInfo& bodyInfo = GetBodyInfo();
  821.  
  822.                 vTargetPos = pTarget->GetPos();
  823.                 vDir = vTargetPos - bodyInfo.vFirePos;
  824.  
  825.                 if (GetSubType() == CAIObject::STP_HELI)
  826.                 {
  827.                         // (MATT) I'm very dubious about this code {2009/02/04}
  828.                         if (m_refLooseAttentionTarget.IsValid())
  829.                                 m_State.vLookTargetPos = vTargetPos;
  830.                         else
  831.                                 m_State.vLookTargetPos.zero();
  832.  
  833.                 }
  834.                 else if (vDir.GetLength() > 5.0 && !AllowedToFire())
  835.                 {
  836.                         Vec3 check1(m_State.vLookTargetPos - bodyInfo.vFirePos);
  837.                         Vec3 check2(vTargetPos - bodyInfo.vEyePos);
  838.                         check1.NormalizeSafe();
  839.                         check2.NormalizeSafe();
  840.                         if (check1.Dot(check2) < cosf(DEG2RAD(5.0f)))
  841.                         {
  842.                                 m_State.vLookTargetPos = m_State.vShootTargetPos = m_State.vAimTargetPos = bodyInfo.vEyePos + vDir * 10.f;
  843.                         }
  844.                 }
  845.         }
  846.         else
  847.         {
  848.                 if (GetSubType() == CAIObject::STP_HELI)
  849.                 {
  850.                         m_State.vLookTargetPos.zero();
  851.                 }
  852.                 else if (!AllowedToFire())
  853.                 {
  854.                         const SAIBodyInfo& bodyInfo = GetBodyInfo();
  855.                         m_State.vLookTargetPos = m_State.vShootTargetPos = m_State.vAimTargetPos = bodyInfo.vEyePos + bodyInfo.vFireDir * 10.f;
  856.                         ;
  857.                 }
  858.         }
  859. }
  860.  
  861. void CAIVehicle::AlertPuppets(void)
  862. {
  863.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  864.  
  865.         if (GetSubType() != CAIObject::STP_CAR)
  866.                 return;
  867.  
  868.         if (!GetPhysics())
  869.                 return;
  870.  
  871.         ActorLookUp& lookUp = *gAIEnv.pActorLookUp;
  872.         lookUp.Prepare(ActorLookUp::Position | ActorLookUp::Proxy);
  873.  
  874.         pe_status_dynamics dSt;
  875.         GetPhysics()->GetStatus(&dSt);
  876.         Vec3 v = dSt.v;
  877.         v.z = 0;
  878.         const float coeff = 0.4f;
  879.         float fv = coeff * v.GetLength();
  880.  
  881.         if (fv < 0.5f)
  882.                 return;
  883.  
  884.         Vec3 vn(v);
  885.         vn.Normalize();
  886.  
  887.         IEntity* pVehicleEntity = GetEntity();
  888.  
  889.         // Find the vehicle rectangle to avoid
  890.         AABB localBounds;
  891.         GetEntity()->GetLocalBounds(localBounds);
  892.         const Matrix34& tm = GetEntity()->GetWorldTM();
  893.         SAIRect3 r;
  894.         GetFloorRectangleFromOrientedBox(tm, localBounds, r);
  895.         // Extend the box based on velocity.
  896.         Vec3 vel = dSt.v;
  897.         const float lookAheadTime = 3.0f;
  898.         float speedu = r.axisu.Dot(vel) * lookAheadTime;
  899.         float speedv = r.axisv.Dot(vel) * lookAheadTime;
  900.         if (speedu > 0)
  901.                 r.max.x += speedu;
  902.         else
  903.                 r.min.x += speedu;
  904.         if (speedv > 0)
  905.                 r.max.y += speedv;
  906.         else
  907.                 r.min.y += speedv;
  908.  
  909.         if (IsPlayerInside())
  910.         {
  911.                 r.min.y -= 1.0f;
  912.                 r.max.y += 1.0f;
  913.         }
  914.         float avoidOffset = (r.max.x - r.min.x) / 2 + 0.5f;
  915.  
  916.         static bool debugdraw = false;
  917.  
  918.         if (debugdraw)
  919.         {
  920.                 const unsigned maxpts = 4;
  921.                 Vec3 rect[maxpts];
  922.                 rect[0] = r.center + r.axisu * r.min.x + r.axisv * r.min.y;
  923.                 rect[1] = r.center + r.axisu * r.max.x + r.axisv * r.min.y;
  924.                 rect[2] = r.center + r.axisu * r.max.x + r.axisv * r.max.y;
  925.                 rect[3] = r.center + r.axisu * r.min.x + r.axisv * r.max.y;
  926.                 unsigned last = maxpts - 1;
  927.                 for (unsigned i = 0; i < maxpts; ++i)
  928.                 {
  929.                         GetAISystem()->AddDebugLine(rect[last], rect[i], 255, 0, 0, 0.2f);
  930.                         last = i;
  931.                 }
  932.         }
  933.  
  934.         const float distToPathThr = (r.max.x - r.min.x) / 2 + 0.5f;
  935.         const float dangerRange = max(r.min.GetLength(), r.max.GetLength()) * 1.5f;
  936.         const float dangerRangeSq = sqr(dangerRange);
  937.  
  938.         size_t activeCount = lookUp.GetActiveCount();
  939.  
  940.         for (size_t actorIndex = 0; actorIndex < activeCount; ++actorIndex)
  941.         {
  942.                 CAIActor* pAIActor = lookUp.GetActor<CAIActor>(actorIndex);
  943.                 CPuppet* pPuppet = 0;
  944.  
  945.                 // Skip distant vehicles
  946.                 if (Distance::Point_Point2DSq(lookUp.GetPosition(actorIndex), r.center) > dangerRangeSq)
  947.                 {
  948.                         pPuppet = pAIActor->CastToCPuppet();
  949.                         if (!pPuppet || pPuppet->GetType() == AIOBJECT_VEHICLE)
  950.                                 continue;
  951.  
  952.                         if (pPuppet->GetAvoidedVehicle() == this)
  953.                         {
  954.                                 if (pPuppet->GetVehicleAvoidingTime() > 3000)
  955.                                 {
  956.                                         CCCPOINT(CAIVehicle_AlertPuppets_SignalVehicle);
  957.                                         pPuppet->SetAvoidedVehicle(NILREF);
  958.                                         pPuppet->SetSignal(1, "OnEndVehicleDanger", GetEntity());
  959.                                 }
  960.                         }
  961.  
  962.                         continue;
  963.                 }
  964.                 else
  965.                 {
  966.                         pPuppet = pAIActor->CastToCPuppet();
  967.                         if (!pPuppet || pPuppet->GetType() == AIOBJECT_VEHICLE)
  968.                                 continue;
  969.                 }
  970.  
  971.                 assert(pPuppet);
  972.  
  973.                 // Skip puppets in vehicles.
  974.                 if (lookUp.GetProxy(actorIndex)->GetLinkedVehicleEntityId())
  975.                         continue;
  976.  
  977.                 bool bNearPath = false;
  978.                 Vec3 puppetDir = pPuppet->GetPos() - r.center;
  979.  
  980.                 float x = r.axisu.Dot(puppetDir);
  981.                 float y = r.axisv.Dot(puppetDir);
  982.  
  983.                 Vec3 pathPosOut(ZERO);
  984.                 float distToPath = 0;
  985.  
  986.                 if (!m_Path.Empty())
  987.                 {
  988.                         float distAlongPath = 0;
  989.                         distToPath = m_Path.GetDistToPath(pathPosOut, distAlongPath, pPuppet->GetPos(), dangerRange, false);//false ->2D only
  990.                         if (distToPath <= distToPathThr + pPuppet->GetParameters().m_fPassRadius)
  991.                                 bNearPath = true;
  992.                 }
  993.  
  994.                 const float pr = pPuppet->GetParameters().m_fPassRadius;
  995.  
  996.                 if (bNearPath || m_Path.Empty() && x >= (r.min.x - pr) && x <= (r.max.x + pr) && y >= (r.min.y - pr) && y <= (r.max.y + pr))
  997.                 {
  998.                         Vec3 move(ZERO);
  999.                         if (bNearPath && distToPath > 0.1f && Distance::Point_Point2DSq(pPuppet->GetPos(), pathPosOut) > sqr(0.1f))
  1000.                         {
  1001.                                 Vec3 norm = pPuppet->GetPos() - pathPosOut;
  1002.                                 norm.z = 0;
  1003.                                 norm.Normalize();
  1004.                                 move = norm * (avoidOffset + 2.0f - distToPath);
  1005.                         }
  1006.                         else
  1007.                         {
  1008.                                 move = r.axisv * (avoidOffset + 2.0f - fabsf(y));
  1009.                                 if (y < 0.0f)
  1010.                                         move = -move;
  1011.                         }
  1012.  
  1013.                         // Note: There used to be a CAISystem.IsPathWorth() check here, but it was removed because of the huge performance peaks.
  1014.                         // Now instead the stick has larger end accuracy (that is, does not need to find exact target location).
  1015.                         Vec3 avoidPos = pPuppet->GetPos() + move;
  1016.                         if (debugdraw)
  1017.                         {
  1018.                                 GetAISystem()->AddDebugSphere(pPuppet->GetPos() + Vec3(0, 0, 2), 0.25f, 255, 255, 255, 0.2f);
  1019.                                 GetAISystem()->AddDebugLine(pPuppet->GetPos(), avoidPos, 255, 255, 255, 0.2f);
  1020.                                 GetAISystem()->AddDebugLine(avoidPos - Vec3(0, 0, 10), avoidPos + Vec3(0, 0, 10), 255, 255, 255, 0.2f);
  1021.                         }
  1022.  
  1023.                         if (pPuppet->GetAvoidedVehicle() != this)
  1024.                         {
  1025.                                 AISignalExtraData* pData = new AISignalExtraData;
  1026.                                 pData->point2 = avoidPos;
  1027.                                 pData->point = vn;
  1028.                                 pPuppet->SetSignal(1, "OnVehicleDanger", GetEntity(), pData);
  1029.                         }
  1030.                         pPuppet->SetAvoidedVehicle(GetWeakRef(this));
  1031.  
  1032.                         // Update pos.
  1033.                         CAIObject* pAvoidTarget = pPuppet->GetOrCreateSpecialAIObject(AISPECIAL_VEHICLE_AVOID_POS);
  1034.                         pAvoidTarget->SetPos(avoidPos, vn);
  1035.  
  1036.                 }
  1037.                 else if (pPuppet->GetAvoidedVehicle() == this)
  1038.                 {
  1039.                         //check rotation around Z axis (2D)
  1040.                         if (!(fabs(dSt.w.z) > 0.2f && fv > 0.7f)) // if vehicle is not spinning like a tank
  1041.                         {
  1042.                                 if (pPuppet->GetVehicleAvoidingTime() > 3000)
  1043.                                 {
  1044.                                         pPuppet->SetAvoidedVehicle(NILREF);
  1045.                                         pPuppet->SetSignal(1, "OnEndVehicleDanger", GetEntity());
  1046.                                 }
  1047.                         }
  1048.                 }
  1049.         }
  1050. }
  1051.  
  1052. void CAIVehicle::Serialize(TSerialize ser)
  1053. {
  1054.         CPuppet::Serialize(ser);
  1055.         ser.BeginGroup("AIVehicle");
  1056.         {
  1057.                 ser.Value("m_bDriverInside", m_bDriverInside);
  1058.                 ser.Value("m_bPoweredUp", m_bPoweredUp);
  1059.                 ser.Value("m_ShootPhase", m_ShootPhase);
  1060.                 ser.Value("m_vDeltaTarget", m_vDeltaTarget);
  1061.  
  1062.                 if (ser.IsReading())
  1063.                 {
  1064.                         CAISystem* pAISystem = GetAISystem();
  1065.  
  1066.                         m_fNextFiringTime = pAISystem->GetFrameStartTime();
  1067.                         m_fFiringStartTime = pAISystem->GetFrameStartTime();
  1068.                         m_fFiringPauseTime = pAISystem->GetFrameStartTime();
  1069.                 }
  1070.         }
  1071.         ser.EndGroup();
  1072. }
  1073.  
  1074. bool CAIVehicle::GetEnemyTarget(int objectType, Vec3& hitPosition, float fDamageRadius2, CAIObject** pTarget)
  1075. {
  1076.         *pTarget = NULL;
  1077.  
  1078.         AIObjectOwners::iterator ai = gAIEnv.pAIObjectManager->m_Objects.find(objectType);
  1079.         AIObjectOwners::iterator aiend = gAIEnv.pAIObjectManager->m_Objects.end();
  1080.  
  1081.         while (ai != aiend)
  1082.         {
  1083.                 // (MATT)       Strong, so always valid {2009/03/25}
  1084.                 CAIObject* pObject = ai->second.GetAIObject();
  1085.                 if (pObject->GetType() != objectType)
  1086.                         break;
  1087.                 if (pObject->IsEnabled())
  1088.                 {
  1089.                         Vec3 dir = pObject->GetPos() - hitPosition;
  1090.                         float dist2 = dir.GetLengthSquared();
  1091.                         if (dist2 < fDamageRadius2)
  1092.                         {
  1093.                                 CAIActor* pActor = pObject->CastToCAIActor();
  1094.                                 if (pActor && IsHostile(pObject, false) == false)
  1095.                                 {
  1096.                                         if (GetEntityID() != pObject->GetEntityID())
  1097.                                         {
  1098.                                                 *pTarget = NULL;
  1099.                                                 return false;
  1100.                                         }
  1101.                                 }
  1102.                                 else
  1103.                                         *pTarget = pObject;
  1104.                         }
  1105.                 }
  1106.                 ++ai;
  1107.         }
  1108.         return true;
  1109. }
  1110.  
  1111. //
  1112. //------------------------------------------------------------------------------------------------------------------
  1113. bool CAIVehicle::HandleVerticalMovement(const Vec3& targetPos)
  1114. {
  1115.  
  1116.         if (m_bPoweredUp)
  1117.                 return false;
  1118.  
  1119.         Vec3 myPos(GetPos());
  1120.         Vec3 diff(targetPos - GetPos());
  1121.  
  1122.         Vec3 diff2d(diff);
  1123.         diff2d.z = 0;
  1124.         float ratio = diff2d.len2() > 0 ? fabs(diff.z) / diff2d.len() : fabs(diff.z);
  1125.         if (0)
  1126.                 if (ratio < 2.0f)
  1127.                 {
  1128.                         m_bPoweredUp = true;
  1129.                         return false;
  1130.                 }
  1131.  
  1132.         //      m_State.vMoveDir = diff;
  1133.         //      m_State.vMoveDir.normalize();
  1134.         m_State.vMoveDir = Vec3(0, 0, 1);
  1135.         float zScale = fabs(diff.z);
  1136.         if (zScale < 5 || diff.z < 0.0f)
  1137.         {
  1138.                 m_bPoweredUp = true;
  1139.                 return false;
  1140.         }
  1141.         m_State.fDesiredSpeed = 5.0f;
  1142.         return true;
  1143. }
  1144.  
  1145. //
  1146. //------------------------------------------------------------------------------------------------------------------
  1147. bool CAIVehicle::IsDriverInside() const
  1148. {
  1149.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  1150.         if (m_bEnabled)
  1151.                 return true;
  1152.         if (m_driverInsideCheck == -1)
  1153.                 m_driverInsideCheck = GetDriverEntity() != 0 ? 1 : 0;
  1154.         return m_driverInsideCheck == 1;
  1155. }
  1156.  
  1157. //
  1158. //------------------------------------------------------------------------------------------------------------------
  1159. bool CAIVehicle::IsPlayerInside()
  1160. {
  1161.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  1162.         if (m_bEnabled)
  1163.                 return true;
  1164.         if (m_playerInsideCheck == -1)
  1165.         {
  1166.                 CAIActor* pDriver = GetDriver();
  1167.                 m_playerInsideCheck = (pDriver && pDriver->GetAIType() == AIOBJECT_PLAYER ? 1 : 0);
  1168.         }
  1169.         return m_playerInsideCheck == 1;
  1170. }
  1171.  
  1172. //
  1173. //------------------------------------------------------------------------------------------------------------------
  1174. EntityId CAIVehicle::GetDriverEntity() const
  1175. {
  1176.         IAIActorProxy* pProxy = GetProxy();
  1177.  
  1178.         return (pProxy ? pProxy->GetLinkedDriverEntityId() : 0);
  1179. }
  1180.  
  1181. //
  1182. //------------------------------------------------------------------------------------------------------------------
  1183. CAIActor* CAIVehicle::GetDriver() const
  1184. {
  1185.         CAIActor* pDriverActor = NULL;
  1186.  
  1187.         const EntityId driverId = GetDriverEntity();
  1188.         if (driverId > 0)
  1189.         {
  1190.                 IEntity* pDriverEntity = gEnv->pEntitySystem->GetEntity(driverId);
  1191.                 IAIObject* pDriverAI = pDriverEntity ? pDriverEntity->GetAI() : NULL;
  1192.                 pDriverActor = CastToCAIActorSafe(pDriverAI);
  1193.         }
  1194.  
  1195.         return pDriverActor;
  1196. }
  1197.  
  1198. //===================================================================
  1199. // GetPathFollowerParams
  1200. //===================================================================
  1201. void CAIVehicle::GetPathFollowerParams(PathFollowerParams& outParams) const
  1202. {
  1203.         CPuppet::GetPathFollowerParams(outParams);
  1204.  
  1205.         outParams.endAccuracy = 1.5f;
  1206.         outParams.isVehicle = true;
  1207. }
  1208.  
  1209. //
  1210. //------------------------------------------------------------------------------------------------------------------
  1211.  
downloadAIVehicle.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