BVB Source Codes

CRYENGINE Show BehaviorTreeNodes_Helicopter.cpp Source code

Return Download CRYENGINE: download BehaviorTreeNodes_Helicopter.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 "BehaviorTreeNodes_Helicopter.h"
  5.  
  6. #include <CryAISystem/BehaviorTree/Action.h>
  7. #include <CryAISystem/BehaviorTree/IBehaviorTree.h>
  8.  
  9. #include "PipeUser.h"
  10. #include "AIPlayer.h"
  11. #include "Puppet.h"
  12.  
  13. #include <CryMath/Cry_Geo.h>
  14. #include <CryMath/Cry_GeoDistance.h>
  15. #include <CryMath/Cry_GeoOverlap.h>
  16.  
  17. #include "FlyHelpers_Tactical.h"
  18. #include "FlyHelpers_PathFollower.h"
  19.  
  20. #include "AIPlayer.h"
  21. #include "BehaviorTreeManager.h"
  22.  
  23. #define MIN_ORIENTATION_SPEED_FACTOR 0.25f
  24. #define MIN_ORIENTATION_SPEED_RANGE  (1.0f + MIN_ORIENTATION_SPEED_FACTOR)
  25.  
  26. namespace FlyHelpers
  27. {
  28. ILINE PathEntityIn CreatePathEntityIn(const CPipeUser* pPipeUser)
  29. {
  30.         CRY_ASSERT(pPipeUser);
  31.  
  32.         PathEntityIn pathEntityIn;
  33.  
  34.         pathEntityIn.position = pPipeUser->GetPos();
  35.         pathEntityIn.forward = pPipeUser->GetViewDir();
  36.         pathEntityIn.velocity = pPipeUser->GetVelocity();
  37.  
  38.         return pathEntityIn;
  39. }
  40.  
  41. ILINE void SendEvent(CPipeUser* pPipeUser, const char* eventName)
  42. {
  43.         CRY_ASSERT(pPipeUser);
  44.         CRY_ASSERT(eventName);
  45.  
  46.         SEntityEvent event(ENTITY_EVENT_SCRIPT_EVENT);
  47.         event.nParam[0] = (INT_PTR)(eventName);
  48.         event.nParam[1] = IEntityClass::EVT_BOOL;
  49.         static const bool s_value = true;
  50.         event.nParam[2] = (INT_PTR)(&s_value);
  51.  
  52.         IEntity* pEntity = pPipeUser->GetEntity();
  53.         pEntity->SendEvent(event);
  54. }
  55.  
  56. float CalculateAdHocSpeedMultiplierForOrientation(const PathEntityIn& pathEntityIn, const PathEntityOut& pathEntityOut)
  57. {
  58.         // TODO: This is temp test code that needs revisiting.
  59.         const Vec3 currentMoveDirection = pathEntityIn.velocity.GetNormalizedSafe(pathEntityIn.forward);
  60.  
  61.         const float lookDirectionDotMoveDirection = pathEntityOut.lookDirection.Dot(currentMoveDirection);
  62.         const float lookDirectionFactor = max(0.0f, lookDirectionDotMoveDirection);
  63.         const float lookDirectionFactorSquared = lookDirectionFactor * lookDirectionFactor;
  64.         const float orientationSpeedFactor = (MIN_ORIENTATION_SPEED_FACTOR + lookDirectionFactorSquared) / MIN_ORIENTATION_SPEED_RANGE;
  65.  
  66.         const float lookDirectionDotForward = pathEntityOut.lookDirection.Dot(pathEntityIn.forward);
  67.         const float lookDirectionFactor2 = max(0.0f, lookDirectionDotForward);
  68.         const float lookDirectionFactorSquared2 = lookDirectionFactor2 * lookDirectionFactor2;
  69.         const float orientationSpeedFactor2 = (MIN_ORIENTATION_SPEED_FACTOR + lookDirectionFactorSquared2) / MIN_ORIENTATION_SPEED_RANGE;
  70.  
  71.         const float speedMultiplier = orientationSpeedFactor * orientationSpeedFactor2;
  72.         return speedMultiplier;
  73. }
  74. }
  75.  
  76. //////////////////////////////////////////////////////////////////////////
  77. namespace BehaviorTree
  78. {
  79. bool GetClampedXmlAttribute(const XmlNodeRef& xml, const char* const attributeName, float& valueInOut, const float minValue, const float maxValue)
  80. {
  81.         CRY_ASSERT(minValue <= maxValue);
  82.  
  83.         const bool readAttributeSuccesss = xml->getAttr(attributeName, valueInOut);
  84.         if (readAttributeSuccesss)
  85.         {
  86.                 valueInOut = clamp_tpl(valueInOut, minValue, maxValue);
  87.         }
  88.         return readAttributeSuccesss;
  89. }
  90.  
  91. class Hover
  92.         : public Action
  93. {
  94. public:
  95.         struct RuntimeData
  96.         {
  97.                 Vec3 targetPosition;
  98.  
  99.                 RuntimeData() : targetPosition(ZERO)
  100.                 {
  101.                 }
  102.         };
  103.  
  104.         virtual void OnInitialize(const UpdateContext& context) override
  105.         {
  106.                 RuntimeData& runtimeData = GetRuntimeData<RuntimeData>(context);
  107.                 runtimeData.targetPosition = context.entity.GetAI()->CastToCPipeUser()->GetPos();
  108.         }
  109.  
  110.         virtual Status Update(const UpdateContext& context) override
  111.         {
  112.                 RuntimeData& runtimeData = GetRuntimeData<RuntimeData>(context);
  113.  
  114.                 CPipeUser* pPipeUser = context.entity.GetAI()->CastToCPipeUser();
  115.  
  116.                 const Vec3 currentPosition = pPipeUser->GetPos();
  117.                 const Vec3 velocity = pPipeUser->GetVelocity();
  118.                 const float speed = velocity.GetLength();
  119.  
  120.                 pPipeUser->m_State.predictedCharacterStates.nStates = 0;
  121.                 const Vec3 currentPositionToTargetPosition = runtimeData.targetPosition - currentPosition;
  122.                 pPipeUser->m_State.vMoveDir = currentPositionToTargetPosition.GetNormalizedSafe(Vec3(ZERO));
  123.                 pPipeUser->m_State.fDistanceToPathEnd = 0;
  124.  
  125.                 // TODO: Make this frame rate independent.
  126.                 //const float desiredSpeed = max( 0.0f, ( speed * 0.6f ) - 0.2f );
  127.                 const float desiredSpeed = 0.5f;
  128.                 pPipeUser->m_State.fDesiredSpeed = desiredSpeed;
  129.                 pPipeUser->m_State.fTargetSpeed = desiredSpeed;
  130.  
  131.                 return Running;
  132.         }
  133. };
  134.  
  135. class FlyShoot
  136.         : public Action
  137. {
  138. public:
  139.         struct RuntimeData
  140.         {
  141.         };
  142.  
  143.         FlyShoot()
  144.                 : m_useSecondaryWeapon(false)
  145.         {
  146.         }
  147.  
  148.         virtual LoadResult LoadFromXml(const XmlNodeRef& xml, const LoadContext& context) override
  149.         {
  150.                 m_useSecondaryWeapon = false;
  151.                 xml->getAttr("useSecondaryWeapon", m_useSecondaryWeapon);
  152.  
  153.                 return LoadSuccess;
  154.         }
  155.  
  156.         virtual void OnInitialize(const UpdateContext& context) override
  157.         {
  158.                 CPipeUser* pPipeUser = context.entity.GetAI()->CastToCPipeUser();
  159.                 pPipeUser->SetFireTarget(GetWeakRef(static_cast<CAIObject*>(pPipeUser->GetAttentionTarget())));
  160.  
  161.                 if (!m_useSecondaryWeapon)
  162.                 {
  163.                         pPipeUser->SetFireMode(FIREMODE_FORCED);
  164.                         pPipeUser->m_State.fire = eAIFS_On;
  165.                 }
  166.         }
  167.  
  168.         virtual Status Update(const UpdateContext& context) override
  169.         {
  170.                 if (m_useSecondaryWeapon)
  171.                 {
  172.                         CPipeUser* pPipeUser = context.entity.GetAI()->CastToCPipeUser();
  173.                         Vec3 aimingPosition(ZERO);
  174.                         const bool validAimingPosition = CalculateAimingPosition(pPipeUser, aimingPosition);
  175.                         if (validAimingPosition)
  176.                         {
  177.                                 SOBJECTSTATE& pipeUserState = pPipeUser->m_State;
  178.  
  179.                                 pPipeUser->SetFireMode(FIREMODE_VEHICLE);
  180.                                 pipeUserState.fireSecondary = eAIFS_On;
  181.                                 pipeUserState.secondaryIndex = SOBJECTSTATE::eFireControllerIndex_All;
  182.  
  183.                                 pipeUserState.vAimTargetPos = aimingPosition;
  184.                                 pipeUserState.aimTargetIsValid = true;
  185.                         }
  186.                         else
  187.                         {
  188.                                 // We do not care about failure cases when we cannot find a valid aim position.
  189.                                 return Running;
  190.                         }
  191.                 }
  192.                 return Running;
  193.         }
  194.  
  195.         virtual void OnTerminate(const UpdateContext& context) override
  196.         {
  197.                 CPipeUser* pPipeUser = context.entity.GetAI()->CastToCPipeUser();
  198.                 pPipeUser->SetFireTarget(NILREF);
  199.  
  200.                 pPipeUser->SetFireMode(FIREMODE_VEHICLE);
  201.                 if (m_useSecondaryWeapon)
  202.                 {
  203.                         pPipeUser->m_State.fireSecondary = eAIFS_Off;
  204.                         pPipeUser->m_State.secondaryIndex = SOBJECTSTATE::eFireControllerIndex_None;
  205.                 }
  206.                 else
  207.                 {
  208.                         pPipeUser->m_State.fire = eAIFS_Off;
  209.                 }
  210.         }
  211.  
  212. private:
  213.  
  214.         bool CalculateAimingPosition(CPipeUser* pPipeUser, Vec3& aimingPositionOut) const
  215.         {
  216.                 aimingPositionOut = Vec3(ZERO);
  217.                 IAIObject* pAttentionTarget = pPipeUser->GetAttentionTarget();
  218.                 if (pAttentionTarget)
  219.                 {
  220.                         aimingPositionOut = pAttentionTarget->GetPos();
  221.                         CPuppet* pPuppet = pPipeUser->CastToCPuppet();
  222.                         if (pPuppet)
  223.                         {
  224.                                 const float maxRadiansForAdjustingFireTargetPosition = DEG2RAD(5.5f);
  225.                                 const float missExtraOffsef = 1.0f;
  226.                                 const bool canHitTarget = true;
  227.                                 pPuppet->AdjustFireTarget(static_cast<CAIObject*>(pAttentionTarget), aimingPositionOut, canHitTarget, missExtraOffsef, maxRadiansForAdjustingFireTargetPosition, &aimingPositionOut);
  228.                         }
  229.                         return true;
  230.                 }
  231.  
  232.                 return false;
  233.         }
  234.  
  235. private:
  236.         bool m_useSecondaryWeapon;
  237. };
  238.  
  239. class WaitAlignedWithAttentionTarget
  240.         : public Action
  241. {
  242. public:
  243.         struct RuntimeData
  244.         {
  245.         };
  246.  
  247.         WaitAlignedWithAttentionTarget()
  248.                 : m_toleranceDegrees(20.0f)
  249.         {
  250.         }
  251.  
  252.         virtual LoadResult LoadFromXml(const XmlNodeRef& xml, const LoadContext& context) override
  253.         {
  254.                 GetClampedXmlAttribute(xml, "toleranceDegrees", m_toleranceDegrees, 0.0f, 180.0f);
  255.                 return LoadSuccess;
  256.         }
  257.  
  258.         virtual Status Update(const UpdateContext& context) override
  259.         {
  260.                 CPipeUser* pPipeUser = context.entity.GetAI()->CastToCPipeUser();
  261.  
  262.                 IAIObject* pAttentionTarget = pPipeUser->GetAttentionTarget();
  263.                 IF_UNLIKELY (!pAttentionTarget)
  264.                 {
  265.                         return Failure;
  266.                 }
  267.  
  268.                 const float validFovCos = cos(DEG2RAD(m_toleranceDegrees));
  269.  
  270.                 const Vec3& position = pPipeUser->GetPos();
  271.                 const Vec3 forward = pPipeUser->GetEntity()->GetForwardDir();
  272.  
  273.                 const Vec3& targetPosition = pAttentionTarget->GetPos();
  274.                 const Vec3 directionToTarget = (targetPosition - position).GetNormalizedSafe(Vec3(0, 1, 0));
  275.  
  276.                 const float dot = directionToTarget.Dot(forward);
  277.  
  278.                 const bool inFov = (validFovCos <= dot);
  279.  
  280.                 return inFov ? Success : Running;
  281.         }
  282.  
  283. private:
  284.         float m_toleranceDegrees;
  285. };
  286.  
  287. class Fly
  288.         : public Action
  289. {
  290. public:
  291.         struct RuntimeData
  292.         {
  293.                 FlyHelpers::PathFollower pathFollower;
  294.                 CTimeValue               lastUpdateTime;
  295.                 bool                     isValidPath;
  296.                 bool                     arrivedCloseToPathEndEventSent;
  297.                 bool                     arrivedAtPathEndEventSent;
  298.  
  299.                 RuntimeData()
  300.                         : lastUpdateTime(0.0f)
  301.                         , isValidPath(false)
  302.                         , arrivedCloseToPathEndEventSent(false)
  303.                         , arrivedAtPathEndEventSent(false)
  304.                 {
  305.                 }
  306.         };
  307.  
  308.         Fly()
  309.                 : m_pathEndDistance(1.0f)
  310.                 , m_goToRefPoint(false)
  311.         {
  312.         }
  313.  
  314.         virtual void OnInitialize(const UpdateContext& context) override
  315.         {
  316.                 RuntimeData& runtimeData = GetRuntimeData<RuntimeData>(context);
  317.  
  318.                 runtimeData.arrivedAtPathEndEventSent = false;
  319.                 runtimeData.arrivedCloseToPathEndEventSent = false;
  320.  
  321.                 CPipeUser* pPipeUser = context.entity.GetAI()->CastToCPipeUser();
  322.  
  323.                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(context.entityId);
  324.                 CRY_ASSERT(pEntity);
  325.  
  326.                 IScriptTable* pScriptTable = pEntity->GetScriptTable();
  327.                 IF_UNLIKELY (!pScriptTable)
  328.                 {
  329.                         return;
  330.                 }
  331.  
  332.                 const char* pathName = pPipeUser->GetPathToFollow();
  333.                 CRY_ASSERT(pathName);
  334.  
  335.                 pScriptTable->GetValue("Helicopter_Loop", m_params.loopAlongPath);
  336.                 pScriptTable->GetValue("Helicopter_Speed", m_params.desiredSpeed);
  337.                 pScriptTable->GetValue("Helicopter_StartFromClosestLocation", m_params.startPathFromClosestLocation);
  338.  
  339.                 bool isValidPath = false;
  340.                 SShape path;
  341.                 const bool getPathSuccess = gAIEnv.pNavigation->GetDesignerPath(pathName, path);
  342.                 IF_LIKELY (getPathSuccess)
  343.                 {
  344.                         isValidPath = (!path.shape.empty());
  345.                 }
  346.  
  347.                 runtimeData.isValidPath = isValidPath;
  348.                 if (!isValidPath)
  349.                 {
  350.                         ErrorReporter(*this, context).LogError("Invalid path '%s'", pathName);
  351.                         return;
  352.                 }
  353.  
  354.                 runtimeData.lastUpdateTime = gEnv->pTimer->GetFrameStartTime();
  355.  
  356.                 const FlyHelpers::PathEntityIn pathEntityIn = FlyHelpers::CreatePathEntityIn(pPipeUser);
  357.                 runtimeData.pathFollower.Init(path, m_params, pathEntityIn);
  358.  
  359.                 if (m_goToRefPoint)
  360.                 {
  361.                         const Vec3 targetPosition = pPipeUser->GetRefPoint()->GetPos();
  362.  
  363.                         runtimeData.pathFollower.SetFinalPathLocation(targetPosition);
  364.                 }
  365.  
  366.                 runtimeData.pathFollower.Update(pathEntityIn, 1.0f);
  367.         }
  368.  
  369.         virtual Status Update(const UpdateContext& context) override
  370.         {
  371.                 RuntimeData& runtimeData = GetRuntimeData<RuntimeData>(context);
  372.  
  373.                 IF_UNLIKELY (!runtimeData.isValidPath)
  374.                 {
  375.                         return Failure;
  376.                 }
  377.  
  378.                 CPipeUser* pPipeUser = context.entity.GetAI()->CastToCPipeUser();
  379.                 const FlyHelpers::PathEntityIn pathEntityIn = FlyHelpers::CreatePathEntityIn(pPipeUser);
  380.  
  381.                 const CTimeValue timeNow = gEnv->pTimer->GetFrameStartTime();
  382.                 const CTimeValue timeDelta = timeNow - runtimeData.lastUpdateTime;
  383.                 runtimeData.lastUpdateTime = timeNow;
  384.  
  385.                 // TODO: find a better way to pass on data from flow-graph in run-time (make it event based).
  386.                 IEntity* pEntity = pPipeUser->GetEntity();
  387.                 assert(pEntity != NULL);
  388.                 IScriptTable* pScriptTable = pEntity->GetScriptTable();
  389.                 IF_LIKELY (pScriptTable != NULL)
  390.                 {
  391.                         float desiredSpeed = 0.0f;
  392.                         if (pScriptTable->GetValue("Helicopter_Speed", desiredSpeed))
  393.                         {
  394.                                 runtimeData.pathFollower.SetDesiredSpeed(desiredSpeed);
  395.                         }
  396.                 }
  397.  
  398.                 const float elapsedSeconds = timeDelta.GetSeconds();
  399.                 FlyHelpers::PathEntityOut pathEntityOut = runtimeData.pathFollower.Update(pathEntityIn, elapsedSeconds);
  400.  
  401.                 pPipeUser->m_State.predictedCharacterStates.nStates = 0;
  402.                 pPipeUser->m_State.vMoveDir = pathEntityOut.moveDirection;
  403.                 pPipeUser->m_State.fDistanceToPathEnd = pathEntityOut.distanceToPathEnd;
  404.                 pPipeUser->m_State.vLookTargetPos = pathEntityOut.lookPosition;
  405.  
  406.                 // TODO: Handle threat
  407.  
  408.                 //pPipeUser->SetBodyTargetDir( pathEntityOut.lookDirection );
  409.                 pPipeUser->SetDesiredBodyDirectionAtTarget(pathEntityOut.lookDirection);
  410.  
  411.                 float speedMultiplier = 1.0f;
  412.                 if (!m_goToRefPoint)
  413.                 {
  414.                         speedMultiplier = CalculateAdHocSpeedMultiplierForOrientation(pathEntityIn, pathEntityOut);
  415.                 }
  416.  
  417.                 pPipeUser->m_State.fDesiredSpeed = pathEntityOut.speed * speedMultiplier;
  418.                 pPipeUser->m_State.fTargetSpeed = pathEntityOut.speed * speedMultiplier;
  419.  
  420.                 if (gAIEnv.CVars.DebugPathFinding)
  421.                 {
  422.                         runtimeData.pathFollower.Draw();
  423.  
  424.                         gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(pathEntityIn.position, Col_Yellow, pathEntityIn.position + pathEntityIn.forward, Col_Yellow);
  425.                         gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(pathEntityIn.position, Col_ForestGreen, pathEntityIn.position + pathEntityOut.moveDirection * pathEntityOut.speed, Col_ForestGreen);
  426.                         gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(pathEntityIn.position, Col_BlueViolet, pathEntityIn.position + pathEntityOut.lookDirection * 5.0f, Col_BlueViolet);
  427.  
  428.                         const Vec3 velocity = pPipeUser->GetVelocity();
  429.                         const float speed = velocity.GetLength();
  430.                         IRenderAuxText::DrawLabelF(pathEntityIn.position + Vec3(0, 0, -2.0f), 1.0f, "velocity <%f, %f, %f> speed %f", velocity.x, velocity.y, velocity.z, speed);
  431.                         IRenderAuxText::DrawLabelF(pathEntityIn.position + Vec3(0, 0, -3.5f), 1.0f, "next requested speed %f", pathEntityOut.speed);
  432.                 }
  433.  
  434.                 const float closeToPathEndDistance = max(m_params.decelerateDistance, m_pathEndDistance);
  435.                 const bool arrivedCloseToPathEnd = (pathEntityOut.distanceToPathEnd <= closeToPathEndDistance);
  436.                 if (arrivedCloseToPathEnd && !runtimeData.arrivedCloseToPathEndEventSent)
  437.                 {
  438.                         FlyHelpers::SendEvent(pPipeUser, "ArrivedCloseToPathEnd");
  439.                         runtimeData.arrivedCloseToPathEndEventSent = true;
  440.                 }
  441.  
  442.                 const bool arrivedToPathEnd = (pathEntityOut.distanceToPathEnd <= m_pathEndDistance);
  443.                 if (arrivedToPathEnd)
  444.                 {
  445.                         if (!runtimeData.arrivedAtPathEndEventSent)
  446.                         {
  447.                                 FlyHelpers::SendEvent(pPipeUser, "ArrivedAtPathEnd");
  448.                                 runtimeData.arrivedAtPathEndEventSent = true;
  449.                         }
  450.  
  451.                         return Success;
  452.                 }
  453.                 else
  454.                 {
  455.                         return Running;
  456.                 }
  457.         }
  458.  
  459.         virtual LoadResult LoadFromXml(const XmlNodeRef& xml, const LoadContext& context) override
  460.         {
  461.                 GetClampedXmlAttribute(xml, "desiredSpeed", m_params.desiredSpeed, 0.0f, FLT_MAX);
  462.                 GetClampedXmlAttribute(xml, "pathRadius", m_params.pathRadius, 0.0f, FLT_MAX);
  463.                 GetClampedXmlAttribute(xml, "lookAheadDistance", m_params.lookAheadDistance, 0.0f, FLT_MAX);
  464.                 GetClampedXmlAttribute(xml, "decelerateDistance", m_params.decelerateDistance, 0.0f, FLT_MAX);
  465.                 GetClampedXmlAttribute(xml, "maxStartDistanceAlongNonLoopingPath", m_params.maxStartDistanceAlongNonLoopingPath, 0.0f, FLT_MAX);
  466.                 xml->getAttr("loopAlongPath", m_params.loopAlongPath);
  467.                 xml->getAttr("startPathFromClosestLocation", m_params.startPathFromClosestLocation);
  468.                 GetClampedXmlAttribute(xml, "pathEndDistance", m_pathEndDistance, 0.0f, FLT_MAX);
  469.                 xml->getAttr("goToRefPoint", m_goToRefPoint);
  470.  
  471.                 return LoadSuccess;
  472.         }
  473.  
  474.         virtual void OnTerminate(const UpdateContext& context) override
  475.         {
  476.                 CPipeUser* pPipeUser = context.entity.GetAI()->CastToCPipeUser();
  477.                 FlyHelpers::SendEvent(pPipeUser, "PathFollowingStopped");
  478.         }
  479.  
  480. private:
  481.         FlyHelpers::PathFollowerParams m_params;
  482.         float                          m_pathEndDistance;
  483.         bool                           m_goToRefPoint;
  484. };
  485.  
  486. class FlyForceAttentionTarget
  487.         : public Action
  488. {
  489. public:
  490.         struct RuntimeData
  491.         {
  492.                 EntityId targetEntityId;
  493.  
  494.                 RuntimeData() : targetEntityId(0)
  495.                 {
  496.                 }
  497.         };
  498.  
  499.         virtual void OnInitialize(const UpdateContext& context) override
  500.         {
  501.                 RuntimeData& runtimeData = GetRuntimeData<RuntimeData>(context);
  502.  
  503.                 runtimeData.targetEntityId = 0;
  504.  
  505.                 CPipeUser* pPipeUser = context.entity.GetAI()->CastToCPipeUser();
  506.  
  507.                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(context.entityId);
  508.                 CRY_ASSERT(pEntity);
  509.  
  510.                 IScriptTable* pScriptTable = pEntity->GetScriptTable();
  511.                 IF_UNLIKELY (!pScriptTable)
  512.                 {
  513.                         return;
  514.                 }
  515.  
  516.                 pScriptTable->GetValue("Helicopter_ForcedTargetId", runtimeData.targetEntityId);
  517.         }
  518.  
  519.         virtual Status Update(const UpdateContext& context) override
  520.         {
  521.                 RuntimeData& runtimeData = GetRuntimeData<RuntimeData>(context);
  522.  
  523.                 IEntity* pTargetEntity = gEnv->pEntitySystem->GetEntity(runtimeData.targetEntityId);
  524.                 IF_UNLIKELY (pTargetEntity == NULL)
  525.                 {
  526.                         return Running;
  527.                 }
  528.  
  529.                 IAIObject* pTargetAi = pTargetEntity->GetAI();
  530.                 IF_UNLIKELY (pTargetEntity == NULL)
  531.                 {
  532.                         return Running;
  533.                 }
  534.  
  535.                 context.entity.GetAI()->CastToCPipeUser()->SetAttentionTarget(GetWeakRef(static_cast<CAIObject*>(pTargetAi)));
  536.                 return Running;
  537.         }
  538.  
  539.         virtual void OnTerminate(const UpdateContext& context) override
  540.         {
  541.                 FlyHelpers::SendEvent(context.entity.GetAI()->CastToCPipeUser(), "ForceAttentionTargetFinished");
  542.         }
  543.  
  544. private:
  545. };
  546.  
  547. class FlyAimAtCombatTarget
  548.         : public Action
  549. {
  550. public:
  551.         struct RuntimeData
  552.         {
  553.         };
  554.  
  555.         FlyAimAtCombatTarget()
  556.         {
  557.         }
  558.  
  559.         virtual Status Update(const UpdateContext& context) override
  560.         {
  561.                 CPipeUser* pPipeUser = context.entity.GetAI()->CastToCPipeUser();
  562.  
  563.                 CAIObject* pTargetAi = static_cast<CAIObject*>(pPipeUser->GetAttentionTarget());
  564.                 if (pTargetAi)
  565.                 {
  566.                         const Vec3 position = pPipeUser->GetPos();
  567.                         const Vec3 viewDirection = pPipeUser->GetViewDir();
  568.                         const Vec3 targetPosition = pTargetAi->GetPos();
  569.  
  570.                         Vec3 adjustedTargetPosition = targetPosition;
  571.  
  572.                         CWeakRef<CAIObject> refTarget = GetWeakRef<CAIObject>(pTargetAi);
  573.                         CPuppet* pPuppet = pPipeUser->CastToCPuppet();
  574.                         if (pPuppet)
  575.                         {
  576.                                 pPuppet->UpdateTargetTracking(refTarget, targetPosition);
  577.                                 pPuppet->m_Parameters.m_fAccuracy = 1.0f;
  578.                                 const bool canDamage = pPuppet->CanDamageTarget(pTargetAi);
  579.  
  580.                                 pPuppet->AdjustFireTarget(pTargetAi, targetPosition, canDamage, 1.0f, DEG2RAD(5.5f), &adjustedTargetPosition);
  581.                         }
  582.  
  583.                         const Vec3 targetDirection = (adjustedTargetPosition - position).GetNormalizedSafe(viewDirection);
  584.  
  585.                         pPipeUser->m_State.vLookTargetPos = adjustedTargetPosition;
  586.                         pPipeUser->SetBodyTargetDir(targetDirection);
  587.                         pPipeUser->SetDesiredBodyDirectionAtTarget(targetDirection);
  588.  
  589.                         pPipeUser->m_State.aimTargetIsValid = true;
  590.                         pPipeUser->m_State.vAimTargetPos = adjustedTargetPosition;
  591.                 }
  592.                 else
  593.                 {
  594.                         pPipeUser->m_State.aimTargetIsValid = false;
  595.                 }
  596.  
  597.                 return Running;
  598.         }
  599.  
  600.         virtual void OnTerminate(const UpdateContext& context) override
  601.         {
  602.                 context.entity.GetAI()->CastToCPipeUser()->m_State.aimTargetIsValid = false;
  603.         }
  604. };
  605.  
  606. }
  607.  
  608. //////////////////////////////////////////////////////////////////////////
  609. void RegisterBehaviorTreeNodesHelicopter()
  610. {
  611.         using namespace BehaviorTree;
  612.  
  613.         assert(gAIEnv.pBehaviorTreeManager);
  614.  
  615.         BehaviorTree::IBehaviorTreeManager& manager = *gAIEnv.pBehaviorTreeManager;
  616.  
  617.         REGISTER_BEHAVIOR_TREE_NODE(manager, Fly);
  618.         REGISTER_BEHAVIOR_TREE_NODE(manager, FlyShoot);
  619.         REGISTER_BEHAVIOR_TREE_NODE(manager, WaitAlignedWithAttentionTarget);
  620.         REGISTER_BEHAVIOR_TREE_NODE(manager, Hover);
  621.         REGISTER_BEHAVIOR_TREE_NODE(manager, FlyAimAtCombatTarget);
  622.         REGISTER_BEHAVIOR_TREE_NODE(manager, FlyForceAttentionTarget);
  623. }
  624.  
downloadBehaviorTreeNodes_Helicopter.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