BVB Source Codes

CRYENGINE Show AIProxy.cpp Source code

Return Download CRYENGINE: download AIProxy.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /********************************************************************
  4.    CryGame Source File.
  5.    -------------------------------------------------------------------------
  6.    File name:   AIProxy.cpp
  7.    Version:     v1.00
  8.    Description:
  9.  
  10.    -------------------------------------------------------------------------
  11.    History:
  12.    - 7:10:2004   18:54 : Created by Kirill Bulatsev
  13.    - 2:12:2005           Now talks directly to CryAction interfaces (craig tiller)
  14.    - 2 Mar 2009                         : Evgeny Adamenkov: Removed parameter of type IRenderer in DebugDraw
  15.  
  16.  
  17.    Notes:
  18.    We can't assume that there is just one IGameObject to an entity, because we choose between (at least) Actor and Vehicle objects.
  19.  
  20.  
  21.  *********************************************************************/
  22.  
  23. #include "StdAfx.h"
  24. #include "AIProxy.h"
  25. #include "AI/AIProxyManager.h"
  26. #include <CryAISystem/IAIAction.h>
  27. #include <CryAISystem/IAISystem.h>
  28. #include "AIHandler.h"
  29. #include "IItemSystem.h"
  30. #include "IVehicleSystem.h"
  31. #include <CryAnimation/ICryAnimation.h>
  32. #include "CryAction.h"
  33.  
  34. #include "RangeSignalingSystem/RangeSignaling.h"
  35. #include "SignalTimers/SignalTimers.h"
  36. #include <CryAISystem/IAIDebugRenderer.h>
  37.  
  38. #include "AI/CommunicationHandler.h"
  39.  
  40. #include <CryAISystem/IAIObject.h>
  41. #include <CryAISystem/IAIActor.h>
  42. #include "AnimationGraph/AnimatedCharacter.h"
  43.  
  44. //
  45. //----------------------------------------------------------------------------------------------------------
  46. CAIProxy::CAIProxy(IGameObject* pGameObject) :
  47.         m_pGameObject(pGameObject),
  48.         m_pAIHandler(0),
  49.         m_firing(false),
  50.         m_firingSecondary(false),
  51.         m_fMinFireTime(0),
  52.         m_WeaponShotIsDone(false),
  53.         m_NeedsShootSignal(false),
  54.         m_CurrentWeaponCanFire(false),
  55.         m_UseSecondaryVehicleWeapon(false),
  56.         m_IsDisabled(false),
  57.         m_UpdateAlways(false),
  58.         m_autoDeactivated(false),
  59.         m_currentWeaponId(0),
  60.         m_currentWeaponFiremodeIndex(std::numeric_limits<int>::max()),
  61.         m_pIActor(0),
  62.         m_shotBulletCount(0),
  63.         m_lastShotTime(0.0f),
  64.         m_animActionGoalPipeId(0),
  65.         m_FmodCharacterTypeParam(0),
  66.         m_forcedExecute(0),
  67.         m_weaponListenerId(0),
  68.         m_aimQueryMode(QueryAimFromMovementController)
  69. {
  70.         // (MATT) This used to include a useAIHandler option, but it was always true {2009/04/06}
  71.         // (MATT) This and serialisation are the only places this is set {2009/01/28}
  72.         // (MATT) All the NULL checks on this could go - only Release clears the pointer {2009/04/20}
  73.         m_pAIHandler = new CAIHandler(m_pGameObject);
  74.         m_pAIHandler->Init();
  75.  
  76.         ReloadScriptProperties();
  77.  
  78.         m_commHandler.reset(new CommunicationHandler(*this, m_pGameObject->GetEntity()));
  79. }
  80.  
  81. //
  82. //----------------------------------------------------------------------------------------------------------
  83. CAIProxy::~CAIProxy()
  84. {
  85.         if (m_weaponListenerId != 0)
  86.         {
  87.                 RemoveWeaponListener(GetWeaponFromId(m_weaponListenerId));
  88.         }
  89.  
  90.         if (m_pAIHandler)
  91.                 m_pAIHandler->Release();
  92.  
  93.         CCryAction::GetCryAction()->GetAIProxyManager()->OnAIProxyDestroyed(this);
  94. }
  95.  
  96. //
  97. //----------------------------------------------------------------------------------------------------------
  98. EntityId CAIProxy::GetLinkedDriverEntityId()
  99. {
  100.         IVehicleSystem* pVehicleSystem = CCryAction::GetCryAction()->GetIVehicleSystem();
  101.         IVehicle* pVehicle = pVehicleSystem->GetVehicle(m_pGameObject->GetEntityId());
  102.         if (pVehicle)
  103.                 if (IVehicleSeat* pVehicleSeat = pVehicle->GetSeatById(1))  //1 means driver
  104.                         return pVehicleSeat->GetPassenger();
  105.         return 0;
  106. }
  107.  
  108. //
  109. //----------------------------------------------------------------------------------------------------------
  110. bool CAIProxy::IsDriver()
  111. {
  112.         // (MATT) Surely rather redundant {2009/01/27}
  113.         if (IActor* pActor = GetActor())
  114.         {
  115.                 if (pActor->GetLinkedVehicle())
  116.                 {
  117.                         IVehicleSystem* pVehicleSystem = CCryAction::GetCryAction()->GetIVehicleSystem();
  118.                         IVehicle* pVehicle = pVehicleSystem->GetVehicle(pActor->GetLinkedVehicle()->GetEntityId());
  119.                         if (pVehicle)
  120.                         {
  121.                                 if (IVehicleSeat* pVehicleSeat = pVehicle->GetSeatById(1))  //1 means driver
  122.                                 {
  123.                                         if (m_pGameObject)
  124.                                         {
  125.                                                 EntityId passengerId = pVehicleSeat->GetPassenger();
  126.                                                 EntityId selfId = m_pGameObject->GetEntityId();
  127.                                                 if (passengerId == selfId)
  128.                                                         return true;
  129.                                         }
  130.                                 }
  131.                         }
  132.                 }
  133.         }
  134.  
  135.         return false;
  136. }
  137.  
  138. //----------------------------------------------------------------------------------------------------------
  139. EntityId CAIProxy::GetLinkedVehicleEntityId()
  140. {
  141.         if (IActor* pActor = GetActor())
  142.         {
  143.                 if (pActor->GetLinkedVehicle())
  144.                         return pActor->GetLinkedVehicle()->GetEntityId();
  145.         }
  146.         return 0;
  147. }
  148.  
  149. //----------------------------------------------------------------------------------------------------------
  150. bool CAIProxy::GetLinkedVehicleVisionHelper(Vec3& outHelperPos) const
  151. {
  152.         assert(m_pGameObject);
  153.  
  154.         IActor* pActor = GetActor();
  155.         IVehicle* pVehicle = pActor ? pActor->GetLinkedVehicle() : NULL;
  156.         IVehicleSeat* pVehicleSeat = pVehicle ? pVehicle->GetSeatForPassenger(m_pGameObject->GetEntityId()) : NULL;
  157.         IVehicleHelper* pAIVisionHelper = pVehicleSeat ? pVehicleSeat->GetAIVisionHelper() : NULL;
  158.  
  159.         if (pAIVisionHelper)
  160.         {
  161.                 outHelperPos = pAIVisionHelper->GetWorldSpaceTranslation();
  162.                 return true;
  163.         }
  164.  
  165.         return false;
  166. }
  167.  
  168. //
  169. //----------------------------------------------------------------------------------------------------------
  170. void CAIProxy::QueryBodyInfo(SAIBodyInfo& bodyInfo)
  171. {
  172.         if (IMovementController* pMC = m_pGameObject->GetMovementController())
  173.         {
  174.                 SMovementState moveState;
  175.                 pMC->GetMovementState(moveState);
  176.  
  177.                 bodyInfo.maxSpeed = moveState.maxSpeed;
  178.                 bodyInfo.minSpeed = moveState.minSpeed;
  179.                 bodyInfo.normalSpeed = moveState.normalSpeed;
  180.                 bodyInfo.stance = moveState.stance;
  181.                 bodyInfo.stanceSize = moveState.m_StanceSize;
  182.                 bodyInfo.colliderSize = moveState.m_ColliderSize;
  183.                 bodyInfo.vEyeDir = moveState.eyeDirection;
  184.                 bodyInfo.vEyeDirAnim = moveState.animationEyeDirection;
  185.                 bodyInfo.vEyePos = moveState.eyePosition;
  186.                 bodyInfo.vEntityDir = moveState.entityDirection;
  187.                 bodyInfo.vAnimBodyDir = moveState.animationBodyDirection;
  188.                 bodyInfo.vMoveDir = moveState.movementDirection;
  189.                 bodyInfo.vUpDir = moveState.upDirection;
  190.                 bodyInfo.lean = moveState.lean;
  191.                 bodyInfo.peekOver = moveState.peekOver;
  192.                 bodyInfo.slopeAngle = moveState.slopeAngle;
  193.  
  194.                 bodyInfo.vFirePos = moveState.weaponPosition;
  195.                 bodyInfo.vFireDir = moveState.aimDirection;
  196.                 bodyInfo.isFiring = moveState.isFiring;
  197.                 bodyInfo.isMoving = moveState.isMoving;
  198.  
  199.                 switch (m_aimQueryMode)
  200.                 {
  201.                 case QueryAimFromMovementController:
  202.                         bodyInfo.isAiming = moveState.isAiming;
  203.                         break;
  204.                 case OverriddenAndAiming:
  205.                         bodyInfo.isAiming = true;
  206.                         break;
  207.                 case OverriddenAndNotAiming:
  208.                         bodyInfo.isAiming = false;
  209.                         break;
  210.                 }
  211.  
  212.                 IActor* pActor = GetActor();
  213.                 IVehicle* pVehicle = pActor ? pActor->GetLinkedVehicle() : 0;
  214.                 IEntity* pVehicleEntity = pVehicle ? pVehicle->GetEntity() : 0;
  215.                 bodyInfo.linkedVehicleEntityId = pVehicleEntity ? pVehicleEntity->GetId() : 0;
  216.         }
  217. }
  218.  
  219. bool CAIProxy::QueryBodyInfo(const SAIBodyInfoQuery& query, SAIBodyInfo& bodyInfo)
  220. {
  221.         if (IMovementController* pMC = m_pGameObject->GetMovementController())
  222.         {
  223.                 SStanceState stanceState;
  224.                 if (!pMC->GetStanceState(SStanceStateQuery(query.position, query.target, query.stance, query.lean, query.peekOver, query.defaultPose), stanceState))
  225.                         return false;
  226.  
  227.                 bodyInfo.maxSpeed = 0.0f;
  228.                 bodyInfo.minSpeed = 0.0f;
  229.                 bodyInfo.normalSpeed = 0.0f;
  230.                 bodyInfo.stance = query.stance;
  231.                 bodyInfo.stanceSize = stanceState.m_StanceSize;
  232.                 bodyInfo.colliderSize = stanceState.m_ColliderSize;
  233.                 bodyInfo.vEyeDir = stanceState.eyeDirection;
  234.                 bodyInfo.vEyeDirAnim.zero();
  235.                 bodyInfo.vEyePos = stanceState.eyePosition;
  236.                 bodyInfo.vEntityDir = stanceState.entityDirection;
  237.                 bodyInfo.vAnimBodyDir = stanceState.animationBodyDirection;
  238.                 bodyInfo.vMoveDir.zero();
  239.                 bodyInfo.vUpDir = stanceState.upDirection;
  240.                 bodyInfo.vFirePos = stanceState.weaponPosition;
  241.                 bodyInfo.vFireDir = stanceState.aimDirection;
  242.                 bodyInfo.isAiming = false;
  243.                 bodyInfo.isFiring = false;
  244.                 bodyInfo.isMoving = false;
  245.                 bodyInfo.lean = stanceState.lean;
  246.                 bodyInfo.peekOver = stanceState.peekOver;
  247.                 bodyInfo.linkedVehicleEntityId = 0;
  248.  
  249.                 return true;
  250.         }
  251.  
  252.         return false;
  253. }
  254.  
  255. IEntity* CAIProxy::GetGrabbedEntity() const
  256. {
  257.         IActor* pActor(GetActor());
  258.         if (pActor)
  259.         {
  260.                 return gEnv->pEntitySystem->GetEntity(pActor->GetGrabbedEntityId());
  261.         }
  262.         return 0;
  263. }
  264.  
  265. void CreateTestVoiceLibraryNameFromBasicName(const string& basicName, string& testName)
  266. {
  267.         const string::size_type indexOfLastUnderscore = basicName.find_last_of('_');
  268.         const stack_string testPostfix("_test");
  269.         testName.reserve(basicName.size() + testPostfix.size());
  270.         static const string::size_type npos = -1; // This is the value find_last_of will return if no '_' is found
  271.         testName = basicName.substr(0, indexOfLastUnderscore != npos ? indexOfLastUnderscore : basicName.size());
  272.         testName = string().Format("%s%s", testName.c_str(), testPostfix.c_str());
  273. }
  274.  
  275. const char* CAIProxy::GetVoiceLibraryName(const bool useForcedDefaultName /* = false */) const
  276. {
  277.         IF_UNLIKELY (useForcedDefaultName)
  278.         {
  279.                 return m_voiceLibraryWhenForcingTest.c_str();
  280.         }
  281.         else
  282.         {
  283.                 return m_voiceLibrary.c_str();
  284.         }
  285. }
  286.  
  287. const char* CAIProxy::GetCommunicationConfigName() const
  288. {
  289.         return m_commConfigName.c_str();
  290. }
  291.  
  292. const float CAIProxy::GetFmodCharacterTypeParam() const
  293. {
  294.         return m_FmodCharacterTypeParam;
  295. }
  296.  
  297. const char* CAIProxy::GetBehaviorSelectionTreeName() const
  298. {
  299.         return m_behaviorSelectionTreeName.c_str();
  300. }
  301.  
  302. const char* CAIProxy::GetNavigationTypeName() const
  303. {
  304.         return m_agentTypeName.c_str();
  305. }
  306.  
  307. IWeapon* CAIProxy::QueryCurrentWeapon(EntityId& currentWeaponId)
  308. {
  309.         // Update the cached current weapon first
  310.         UpdateCurrentWeapon();
  311.  
  312.         return GetCurrentWeapon(currentWeaponId);
  313. }
  314.  
  315. IWeapon* CAIProxy::GetCurrentWeapon(EntityId& currentWeaponId) const
  316. {
  317.         currentWeaponId = m_currentWeaponId;
  318.  
  319.         IItem* pItem = CCryAction::GetCryAction()->GetIItemSystem()->GetItem(m_currentWeaponId);
  320.         IWeapon* pWeapon = (pItem ? pItem->GetIWeapon() : NULL);
  321.  
  322.         return pWeapon;
  323. }
  324.  
  325. IWeapon* CAIProxy::GetSecWeapon(const ERequestedGrenadeType prefGrenadeType, ERequestedGrenadeType* pReturnedGrenadeType, EntityId* const pSecondaryWeaponId) const
  326. {
  327.         CRY_ASSERT(prefGrenadeType > eRGT_INVALID && prefGrenadeType < eRGT_COUNT);
  328.  
  329.         if (pSecondaryWeaponId)
  330.                 *pSecondaryWeaponId = 0;
  331.  
  332.         IActor* pActor = GetActor();
  333.         IInventory* pInventory = (pActor != NULL) ? pActor->GetInventory() : NULL;
  334.         if (!pInventory)
  335.                 return NULL;
  336.  
  337.         IEntityClassRegistry* pRegistery = gEnv->pEntitySystem->GetClassRegistry();
  338.         CRY_ASSERT(pRegistery);
  339.  
  340.         EntityId itemEntity = 0;
  341.         IAIObject* pAI = m_pGameObject->GetEntity()->GetAI();
  342.         if (pAI && pAI->GetAIType() == AIOBJECT_PLAYER)
  343.         {
  344.                 // Offhand weapon for player, can be any
  345.                 itemEntity = pInventory->GetItemByClass(pRegistery->FindClass("OffHand"));
  346.         }
  347.         else
  348.         {
  349.                 // EntityIds of what types of grenades we have in our inventory
  350.                 // TODO Hardcoded class names are disgusting, need a better way
  351.                 EntityId pSecWeaponInventory[eRGT_COUNT] =
  352.                 {
  353.                         0,   // eRGT_ANY (if passed in as preferred type, will be skipped)
  354.                         pInventory->GetItemByClass(pRegistery->FindClass("AISmokeGrenades")),
  355.                         pInventory->GetItemByClass(pRegistery->FindClass("AIFlashbangs")),
  356.                         pInventory->GetItemByClass(pRegistery->FindClass("AIGrenades")),
  357.                         pInventory->GetItemByClass(pRegistery->FindClass("AIEMPGrenades")),
  358.                         pInventory->GetItemByClass(pRegistery->FindClass("AIGruntGrenades")),
  359.                 };
  360.  
  361.                 // Check requested type first
  362.                 itemEntity = pSecWeaponInventory[prefGrenadeType];
  363.                 if (pReturnedGrenadeType)
  364.                         *pReturnedGrenadeType = prefGrenadeType;
  365.  
  366.                 if (!itemEntity)
  367.                 {
  368.                         itemEntity = pSecWeaponInventory[eRGT_FRAG_GRENADE];
  369.                         if (pReturnedGrenadeType)
  370.                                 *pReturnedGrenadeType = eRGT_FRAG_GRENADE;
  371.                 }
  372.                 if (!itemEntity)
  373.                 {
  374.                         itemEntity = pSecWeaponInventory[eRGT_FLASHBANG_GRENADE];
  375.                         if (pReturnedGrenadeType)
  376.                                 *pReturnedGrenadeType = eRGT_FLASHBANG_GRENADE;
  377.                 }
  378.                 if (!itemEntity)
  379.                 {
  380.                         itemEntity = pSecWeaponInventory[eRGT_SMOKE_GRENADE];
  381.                         if (pReturnedGrenadeType)
  382.                                 *pReturnedGrenadeType = eRGT_SMOKE_GRENADE;
  383.                 }
  384.                 if (!itemEntity)
  385.                 {
  386.                         itemEntity = pSecWeaponInventory[eRGT_EMP_GRENADE];
  387.                         if (pReturnedGrenadeType)
  388.                                 *pReturnedGrenadeType = eRGT_EMP_GRENADE;
  389.                 }
  390.                 if (!itemEntity)
  391.                 {
  392.                         itemEntity = pSecWeaponInventory[eRGT_GRUNT_GRENADE];
  393.                 }
  394.         }
  395.  
  396.         // Get weapon if we have something in our inventory
  397.         if (itemEntity)
  398.         {
  399.                 if (IItem* pItem = CCryAction::GetCryAction()->GetIItemSystem()->GetItem(itemEntity))
  400.                 {
  401.                         if (pSecondaryWeaponId)
  402.                                 *pSecondaryWeaponId = pItem->GetEntityId();
  403.  
  404.                         return pItem->GetIWeapon();
  405.                 }
  406.         }
  407.  
  408.         if (pReturnedGrenadeType)
  409.                 *pReturnedGrenadeType = eRGT_INVALID;
  410.  
  411.         return 0;
  412. }
  413.  
  414. IFireController* CAIProxy::GetFireController(uint32 controllerNum)
  415. {
  416.         IVehicleSystem* pVehicleSystem = CCryAction::GetCryAction()->GetIVehicleSystem();
  417.  
  418.         if (IVehicle* pVehicle = (IVehicle*) pVehicleSystem->GetVehicle(m_pGameObject->GetEntityId()))
  419.                 return pVehicle->GetFireController(controllerNum);
  420.  
  421.         return NULL;
  422. }
  423.  
  424. //
  425. //----------------------------------------------------------------------------------------------------------
  426. bool CAIProxy::IsEnabled() const
  427. {
  428.         return !m_IsDisabled;
  429. }
  430.  
  431. //
  432. //----------------------------------------------------------------------------------------------------------
  433. void CAIProxy::EnableUpdate(bool enable)
  434. {
  435.         // DO NOT:
  436.         //  1. call SetAIActivation on GameObject
  437.         //  2. call Activate on Entity
  438.         // (this will result in an infinite-ish loop)
  439.  
  440.         bool bNotifyListeners = false;
  441.         m_autoDeactivated = false; // always clear this - it needs to explicitly set by the automation mechanism
  442.  
  443.         if (enable)
  444.         {
  445.                 if (m_IsDisabled)
  446.                         bNotifyListeners = true;
  447.  
  448.                 IAIObject* pAI = m_pGameObject->GetEntity()->GetAI();
  449.                 m_IsDisabled = false;
  450.                 if (pAI)
  451.                         pAI->Event(AIEVENT_ENABLE, NULL);
  452.         }
  453.         else
  454.         {
  455.                 if (!m_IsDisabled)
  456.                         bNotifyListeners = true;
  457.  
  458.                 IAIObject* pAI = m_pGameObject->GetEntity()->GetAI();
  459.                 m_IsDisabled = true;
  460.                 if (pAI)
  461.                         pAI->Event(AIEVENT_DISABLE, NULL);
  462.         }
  463.  
  464.         // Notify listeners
  465.         if (bNotifyListeners)
  466.         {
  467.                 TListeners::const_iterator listener = m_listeners.begin();
  468.                 TListeners::const_iterator listenerEnd = m_listeners.end();
  469.                 for (; listener != listenerEnd; ++listener)
  470.                 {
  471.                         (*listener)->OnAIProxyEnabled(!m_IsDisabled);
  472.                 }
  473.         }
  474.  
  475.         if (IActor* pActor = GetActor())
  476.         {
  477.                 pActor->OnAIProxyEnabled(!m_IsDisabled);
  478.         }
  479. }
  480.  
  481. //
  482. //----------------------------------------------------------------------------------------------------------
  483. void CAIProxy::AddListener(IAIProxyListener* pListener)
  484. {
  485.         CRY_ASSERT(pListener);
  486.         if (std::find(m_listeners.begin(), m_listeners.end(), pListener) == m_listeners.end())
  487.         {
  488.                 m_listeners.push_back(pListener);
  489.  
  490.                 // Notify of current status
  491.                 pListener->OnAIProxyEnabled(!m_IsDisabled);
  492.         }
  493. }
  494.  
  495. //
  496. //----------------------------------------------------------------------------------------------------------
  497. void CAIProxy::RemoveListener(IAIProxyListener* pListener)
  498. {
  499.         CRY_ASSERT(pListener);
  500.         stl::find_and_erase(m_listeners, pListener);
  501. }
  502.  
  503. //
  504. //----------------------------------------------------------------------------------------------------------
  505. void CAIProxy::UpdateMeAlways(bool doUpdateMeAlways)
  506. {
  507.         m_UpdateAlways = doUpdateMeAlways;
  508.         CheckUpdateStatus();
  509. }
  510.  
  511. //
  512. //----------------------------------------------------------------------------------------------------------
  513. void CAIProxy::ResendTargetSignalsNextFrame()
  514. {
  515.         if (m_pAIHandler)
  516.                 m_pAIHandler->ResendTargetSignalsNextFrame();
  517. }
  518.  
  519. //
  520. //----------------------------------------------------------------------------------------------------------
  521. bool CAIProxy::CheckUpdateStatus()
  522. {
  523.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  524.  
  525.         bool update = false;
  526.         // DO NOT call Activate on Entity
  527.         // (this will result in an infinite-ish loop)
  528.         if (gEnv->pAISystem->GetUpdateAllAlways() || m_UpdateAlways)
  529.                 update = m_pGameObject->SetAIActivation(eGOAIAM_Always);
  530.         else
  531.                 update = m_pGameObject->SetAIActivation(eGOAIAM_VisibleOrInRange);
  532.         return update;
  533. }
  534.  
  535. //
  536. //----------------------------------------------------------------------------------------------------------
  537. int CAIProxy::Update(SOBJECTSTATE& state, bool bFullUpdate)
  538. {
  539.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  540.  
  541.         if (!CheckUpdateStatus())
  542.                 return 0;
  543.  
  544.         if (!m_pAIHandler)
  545.                 return 0;
  546.  
  547.         if (bFullUpdate)
  548.                 UpdateMind(state);
  549.  
  550.         if (IsDead() && GetPhysics() == NULL)
  551.         {
  552.                 // killed actor is updated by AI ?
  553.                 return 0;
  554.         }
  555.  
  556.         IActor* pActor = GetActor();
  557.  
  558.         bool fire = (eAIFS_On == state.fire);
  559.         bool fireSec = (eAIFS_On == state.fireSecondary);
  560.         const bool fireBlocking = (eAIFS_Blocking == state.fire || eAIFS_Blocking == state.fireSecondary || eAIFS_Blocking == state.fireMelee);
  561.         bool isAlive(true);
  562.  
  563.         IMovementController* pMC = m_pGameObject->GetMovementController();
  564.         if (pMC)
  565.         {
  566.                 SMovementState moveState;
  567.                 pMC->GetMovementState(moveState);
  568.                 isAlive = moveState.isAlive;
  569.  
  570.                 if (!isAlive)
  571.                 {
  572.                         fire = false;
  573.                         fireSec = false;
  574.                 }
  575.  
  576.                 Vec3 currentPos = m_pGameObject->GetEntity()->GetWorldPos();
  577.  
  578.                 CMovementRequest mr;
  579.  
  580.                 int alertness = GetAlertnessState();
  581.                 mr.SetAlertness(alertness);
  582.  
  583.                 // [DAVID] Set Actor/AC alertness
  584.                 if (pActor != NULL)
  585.                         pActor->SetFacialAlertnessLevel(alertness);
  586.  
  587.                 if (!state.vLookTargetPos.IsZero())
  588.                         mr.SetLookTarget(state.vLookTargetPos);
  589.                 else
  590.                         mr.ClearLookTarget();
  591.  
  592.                 mr.SetLookStyle(state.eLookStyle);
  593.                 mr.SetAllowLowerBodyToTurn(state.bAllowLowerBodyToTurn);
  594.                 mr.SetBodyOrientationMode(state.bodyOrientationMode);
  595.  
  596.                 if (fabsf(state.lean) > 0.01f)
  597.                         mr.SetLean(state.lean);
  598.                 else
  599.                         mr.ClearLean();
  600.  
  601.                 if (fabsf(state.peekOver) > 0.01f)
  602.                         mr.SetPeekOver(state.peekOver);
  603.                 else
  604.                         mr.ClearPeekOver();
  605.  
  606.                 // it is possible that we have a move target but zero speed, in which case we want to turn
  607.                 // on the spot.
  608.                 CTimeValue curTime = gEnv->pTimer->GetFrameStartTime();
  609.                 bool movementAllowed = !fireBlocking && !IsAnimationBlockingMovement() && !GetActorIsFallen();
  610.  
  611.                 bool wantsToMove = false;
  612.                 if (movementAllowed)
  613.                 {
  614.                         wantsToMove = !state.vMoveDir.IsZero() && (state.fDesiredSpeed > 0.0f);
  615.                 }
  616.  
  617.                 if (!wantsToMove)
  618.                 {
  619.                         mr.ClearMoveTarget();
  620.                         mr.SetDesiredSpeed(0.0f);
  621.                         mr.SetPseudoSpeed(state.curActorTargetPhase == eATP_Waiting ? fabs(state.fMovementUrgency) : 0.0f);
  622.                         mr.ClearPrediction();
  623.                 }
  624.                 else
  625.                 {
  626.                         /*
  627.                            ANIM-UNSUPPORTED 2+
  628.                            Give AI the opportunity to pass prediction??
  629.                            if (state.predictedCharacterStates.nStates > 0)
  630.                            {
  631.                            int num = min((int) state.predictedCharacterStates.nStates, (int) SPredictedCharacterStates::maxStates);
  632.                            SPredictedCharacterStates predStates;
  633.                            predStates.nStates = num;
  634.                            pe_status_pos status;
  635.                            GetPhysics()->GetStatus(&status);
  636.                            for (int iPred = 0 ; iPred != num ; ++iPred)
  637.                            {
  638.                             SAIPredictedCharacterState &pred = state.predictedCharacterStates.states[iPred];
  639.                             predStates.states[iPred].deltatime = pred.predictionTime;
  640.                             predStates.states[iPred].position = pred.position;
  641.                             predStates.states[iPred].velocity = pred.velocity;
  642.                             //predStates.states[iPred].rotation.SetIdentity();
  643.                             if (state.allowStrafing || pred.velocity.IsZero(0.01f))
  644.                               predStates.states[iPred].orientation = status.q;
  645.                             else
  646.                               predStates.states[iPred].orientation.SetRotationV0V1(Vec3(0, 1, 0), pred.velocity.GetNormalized());
  647.                            }
  648.                            mr.SetPrediction(predStates);
  649.                            }
  650.                            else*/
  651.                         {
  652.                                 mr.ClearPrediction();
  653.                         }
  654.  
  655.                         // If no real move target is available
  656.                         if (state.vMoveTarget.IsZero())
  657.                         {
  658.                                 // OLD behavior: Estimate a future position (based on velocity)
  659.                                 mr.SetMoveTarget(currentPos + state.vMoveDir.GetNormalized() * min(3.0f, state.fDistanceToPathEnd));
  660.                                 mr.SetDirectionOffFromPath(state.vDirOffPath);
  661.                                 mr.ClearInflectionPoint();
  662.                         }
  663.                         else
  664.                         {
  665.                                 // NEW behavior: Provide exact move target and inflection point based on real PathFollower data.
  666.                                 if (state.continuousMotion)
  667.                                 {
  668.                                         mr.SetMoveTarget(state.vMoveDir * 5.0f + currentPos);
  669.                                 }
  670.                                 else
  671.                                 {
  672.                                         mr.SetMoveTarget(state.vMoveTarget);
  673.                                 }
  674.                                 mr.SetInflectionPoint(state.vInflectionPoint);
  675.                                 mr.SetDirectionOffFromPath(state.vDirOffPath);
  676.                         }
  677.  
  678.                         if (fabs(state.fDesiredSpeed * state.fMovementUrgency) > 0.00001f)
  679.                         {
  680.                                 float speedMul = (float)__fsel(state.fMovementUrgency, 1.0f, -1.0f);
  681.                                 mr.SetDesiredSpeed(speedMul * state.fDesiredSpeed, speedMul * state.fTargetSpeed);
  682.                                 mr.SetPseudoSpeed(fabs(state.fMovementUrgency));
  683.                         }
  684.                         else
  685.                         {
  686.                                 mr.SetDesiredSpeed(0.0f, 0.0f);
  687.                                 mr.SetPseudoSpeed(0.0f);
  688.                         }
  689.  
  690. #if DEBUG_VELOCITY()
  691.                         if (pActor)
  692.                         {
  693.                                 if (const IAnimatedCharacter* pAnimChar = pActor->GetAnimatedCharacter())
  694.                                 {
  695.                                         if (pAnimChar->DebugVelocitiesEnabled())
  696.                                         {
  697.                                                 const Vec3 entityPos = pActor->GetEntity()->GetPos();
  698.  
  699.                                                 // In the following we assume 2D movement. This makes the debug info consistent
  700.                                                 // with the debug info coming from the MovementController (etc), which is 2D too.
  701.                                                 const Vec2 toMoveTarget = Vec2(mr.GetMoveTarget()) - Vec2(entityPos);
  702.                                                 const float distToMoveTarget = toMoveTarget.GetLength();
  703.                                                 const Vec2 dirToMoveTarget = (distToMoveTarget > 0.01f) ? toMoveTarget / distToMoveTarget : Vec2(ZERO);
  704.  
  705.                                                 const float frameTime = (float)gEnv->pTimer->GetFrameTime();
  706.                                                 const QuatT movement(dirToMoveTarget * (mr.GetDesiredSpeed() * frameTime), Quat(IDENTITY));
  707.  
  708.                                                 if (state.vMoveTarget.IsZero())
  709.                                                         pAnimChar->AddDebugVelocity(movement, frameTime, "AIProxy Output (MoveDir)", Col_Plum, false);
  710.                                                 else
  711.                                                         pAnimChar->AddDebugVelocity(movement, frameTime, "AIProxy Output (MoveTarget)", Col_Orchid, false);
  712.                                         }
  713.                                 }
  714.                         }
  715. #endif
  716.                 }
  717.  
  718.                 mr.SetDistanceToPathEnd(state.fDistanceToPathEnd);
  719.  
  720.                 mr.SetStance((EStance)state.bodystate);
  721.  
  722.                 mr.SetAllowStrafing(state.allowStrafing);
  723.  
  724.                 m_pAIHandler->HandleExactPositioning(state, mr);
  725.  
  726.                 if (state.jump)
  727.                         mr.SetJump();
  728.  
  729.                 if (state.aimTargetIsValid && !state.vAimTargetPos.IsZero())
  730.                         mr.SetAimTarget(state.vAimTargetPos);
  731.                 else
  732.                         mr.ClearAimTarget();
  733.  
  734.                 if (fire || fireSec || eAIFS_On == state.fireMelee)
  735.                         mr.SetFireTarget(state.vShootTargetPos);
  736.                 else
  737.                         mr.ClearFireTarget();
  738.  
  739.                 if (state.vForcedNavigation.IsZero())
  740.                 {
  741.                         mr.ClearForcedNavigation();
  742.                 }
  743.                 else
  744.                 {
  745.                         mr.SetForcedNavigation(state.vForcedNavigation);
  746.                         mr.SetDesiredSpeed(state.fForcedNavigationSpeed);
  747.  
  748. #if DEBUG_VELOCITY()
  749.                         if (pActor)
  750.                         {
  751.                                 if (CAnimatedCharacter* pAnimChar = static_cast<CAnimatedCharacter*>(pActor->GetAnimatedCharacter()))
  752.                                 {
  753.                                         if (pAnimChar->DebugVelocitiesEnabled())
  754.                                         {
  755.                                                 float frameTime = (float)gEnv->pTimer->GetFrameTime();
  756.                                                 QuatT movement(state.vForcedNavigation * state.fForcedNavigationSpeed * frameTime, Quat(IDENTITY));
  757.                                                 pAnimChar->AddDebugVelocity(movement, frameTime, "AIProxy Forced Navigation", Col_Salmon, false);
  758.                                         }
  759.                                 }
  760.                         }
  761. #endif
  762.                 }
  763.  
  764.                 if (state.vBodyTargetDir.IsZero())
  765.                         mr.ClearBodyTarget();
  766.                 else
  767.                         mr.SetBodyTarget(currentPos + state.vBodyTargetDir);
  768.  
  769.                 if (state.vDesiredBodyDirectionAtTarget.IsZero())
  770.                         mr.ClearDesiredBodyDirectionAtTarget();
  771.                 else
  772.                         mr.SetDesiredBodyDirectionAtTarget(state.vDesiredBodyDirectionAtTarget);
  773.  
  774.                 if (!state.movementContext)
  775.                         mr.ClearContext();
  776.                 else
  777.                         mr.SetContext(state.movementContext);
  778.  
  779.                 m_pAIHandler->HandleCoverRequest(state, mr);
  780.  
  781.                 m_pAIHandler->HandleMannequinRequest(state, mr);
  782.  
  783.                 // try, and retry once
  784.                 if (!pMC->RequestMovement(mr))
  785.                         pMC->RequestMovement(mr);
  786.         }
  787.  
  788.         UpdateShooting(state, isAlive);
  789.  
  790.         return 0;
  791. }
  792.  
  793. //
  794. //----------------------------------------------------------------------------------------------------------
  795. void CAIProxy::UpdateShooting(const SOBJECTSTATE& state, bool isAlive)
  796. {
  797.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  798.  
  799.         m_WeaponShotIsDone = false;
  800.  
  801.         bool fire = (eAIFS_On == state.fire && !state.aimObstructed);//|| (m_StartWeaponSpinUpTime>0);
  802.         bool fireSec = (eAIFS_On == state.fireSecondary);
  803.         if (!isAlive || !m_CurrentWeaponCanFire)
  804.         {
  805.                 fire = false;
  806.                 fireSec = false;
  807.         }
  808.  
  809.         bool hasFireControl = true;
  810.         IEntity* pEntity = m_pGameObject->GetEntity();
  811.         if (pEntity)
  812.         {
  813.                 IPuppet* pPuppet = CastToIPuppetSafe(pEntity->GetAI());
  814.                 if (pPuppet)
  815.                         hasFireControl = pPuppet->IsFireEnabled();
  816.         }
  817.  
  818.         EntityId currentWeaponId = 0;
  819.         IWeapon* pWeapon = GetCurrentWeapon(currentWeaponId);
  820.  
  821.         if (eAIFS_On == state.fireMelee)
  822.         {
  823.                 if (isAlive && (pWeapon != NULL) && hasFireControl)
  824.                 {
  825.                         enum MeleeType
  826.                         {
  827.                                 ShortMelee,
  828.                                 LongMelee
  829.                         };
  830.  
  831.                         MeleeType meleeType = ShortMelee;
  832.  
  833.                         if (IAIObject* aiObject = m_pAIHandler->m_pEntity->GetAI())
  834.                         {
  835.                                 if (IAIActor* aiActor = aiObject->CastToIAIActor())
  836.                                 {
  837.                                         bool continuousMotion = aiActor->GetState().continuousMotion;
  838.  
  839.                                         if (continuousMotion)
  840.                                         {
  841.                                                 bool moving = aiObject->GetVelocity().GetLengthSquared() > square(0.5f);
  842.                                                 meleeType = moving ? LongMelee : ShortMelee;
  843.                                         }
  844.                                         else
  845.                                         {
  846.                                                 meleeType = IsInCloseMeleeRange(aiObject, aiActor) ? ShortMelee : LongMelee;
  847.                                         }
  848.                                 }
  849.                         }
  850.  
  851.                         if (!IsAnimationBlockingMovement())
  852.                         {
  853.                                 pWeapon->MeleeAttack(meleeType == ShortMelee);
  854.                         }
  855.                 }
  856.  
  857.                 fire = false;
  858.                 fireSec = false;
  859.         }
  860.  
  861.         //---------------------------------------------------------------------------
  862.         if (pWeapon)
  863.         {
  864.                 IFireMode* pFireMode = pWeapon->GetFireMode(pWeapon->GetCurrentFireMode());
  865.                 if (pFireMode)
  866.                         m_firing = pFireMode->IsFiring();
  867.                 bool raise = state.aimObstructed;
  868.                 pWeapon->Query(eWQ_Raise_Weapon, (const void*)&raise);
  869.         }
  870.  
  871.         // firing control
  872.         if (fire && !m_firing && hasFireControl)
  873.         {
  874.                 if (pWeapon && pWeapon->CanFire())
  875.                 {
  876.                         SProjectileLaunchParams launchParams;
  877.                         launchParams.fSpeedScale = state.projectileInfo.fSpeedScale;
  878.                         launchParams.trackingId = state.projectileInfo.trackingId;
  879.                         launchParams.vShootTargetPos = state.vShootTargetPos;
  880.                         pWeapon->StartFire(launchParams);
  881.                         m_firing = true;
  882.                 }
  883.                 else if (IFireController* pFireController = GetFireController())
  884.                 {
  885.                         m_firing = true;
  886.                         pFireController->RequestFire(m_firing);
  887.                         pFireController->UpdateTargetPosAI(state.vAimTargetPos);
  888.                 }
  889.         }
  890.         else if (!fire && m_firing)
  891.         {
  892.                 if (pWeapon && pWeapon->CanStopFire())
  893.                 {
  894.                         pWeapon->StopFire();
  895.                         m_firing = false;
  896.                 }
  897.                 else
  898.                 {
  899.                         if (IFireController* pFireController = GetFireController())
  900.                         {
  901.                                 m_firing = false;
  902.                                 pFireController->RequestFire(m_firing);
  903.                         }
  904.                 }
  905.         }
  906.  
  907.         if (IFireController* pFireController = GetFireController())
  908.         {
  909.                 pFireController->UpdateTargetPosAI(state.vAimTargetPos);
  910.         }
  911.  
  912.         // secondary weapon firing control
  913.         if (fireSec && !m_firingSecondary && hasFireControl)
  914.         {
  915.                 ERequestedGrenadeType returnedGrenadeType = eRGT_INVALID;
  916.                 if (IWeapon* pSecWeapon = GetSecWeapon(state.requestedGrenadeType, &returnedGrenadeType))
  917.                 {
  918.                         SProjectileLaunchParams launchParams;
  919.                         launchParams.fSpeedScale = state.projectileInfo.fSpeedScale;
  920.                         launchParams.trackingId = state.projectileInfo.trackingId;
  921.                         launchParams.vShootTargetPos = state.vShootTargetPos;
  922.                         pSecWeapon->StartFire(launchParams);
  923.  
  924.                         m_firingSecondary = true;
  925.  
  926.                         IEntity* pEnt = m_pGameObject->GetEntity();
  927.                         if (pEnt)
  928.                         {
  929.  
  930.                                 switch (returnedGrenadeType)
  931.                                 {
  932.                                 case eRGT_SMOKE_GRENADE:
  933.                                         SendSignal(AISIGNAL_DEFAULT, "OnSmokeGrenadeThrown", pEnt, NULL);
  934.                                         break;
  935.                                 case eRGT_FLASHBANG_GRENADE:
  936.                                         SendSignal(AISIGNAL_DEFAULT, "OnFlashbangGrenadeThrown", pEnt, NULL);
  937.                                         break;
  938.                                 case eRGT_FRAG_GRENADE:
  939.                                         SendSignal(AISIGNAL_DEFAULT, "OnFragGrenadeThrown", pEnt, NULL);
  940.                                         break;
  941.                                 case eRGT_EMP_GRENADE:
  942.                                         SendSignal(AISIGNAL_DEFAULT, "OnEMPGrenadeThrown", pEnt, NULL);
  943.                                         break;
  944.                                 }
  945.  
  946.                                 // If not specific grenade type was requested, just
  947.                                 // signal to self to inform grenade is now being thrown
  948.                                 IAISignalExtraData* pData = gEnv->pAISystem->CreateSignalExtraData();
  949.                                 pData->iValue = state.requestedGrenadeType;
  950.                                 pData->fValue = state.projectileInfo.fSpeedScale;
  951.                                 pData->point = state.vShootTargetPos;
  952.                                 SendSignal(AISIGNAL_DEFAULT, "OnGrenadeThrown", pEnt, pData);
  953.  
  954.                                 gEnv->pAISystem->FreeSignalExtraData(pData);
  955.                         }
  956.                 }
  957.                 else if (!m_firingSecondary)
  958.                 {
  959.                         uint32 index = state.secondaryIndex;
  960.  
  961.                         while (index & 0xf)
  962.                         {
  963.                                 if (IFireController* pFireController = GetFireController(index & 0xf))
  964.                                 {
  965.                                         pFireController->RequestFire(fireSec);
  966.                                         pFireController->UpdateTargetPosAI(state.vAimTargetPos);
  967.                                 }
  968.  
  969.                                 index >>= 4;
  970.                         }
  971.  
  972.                         m_firingSecondary = true;
  973.                 }
  974.         }
  975.         else if (!fireSec && m_firingSecondary)
  976.         {
  977.                 uint32 index = 1;
  978.                 while (IFireController* pFireController = GetFireController(index))
  979.                 {
  980.                         pFireController->RequestFire(fireSec);
  981.                         ++index;
  982.                 }
  983.  
  984.                 m_firingSecondary = false;
  985.         }
  986.         else if (m_firingSecondary)
  987.         {
  988.                 uint32 index = state.secondaryIndex;
  989.                 while (index & 0xf)
  990.                 {
  991.                         if (IFireController* pFireController = GetFireController(index & 0xf))
  992.                         {
  993.                                 pFireController->UpdateTargetPosAI(state.vAimTargetPos);
  994.                         }
  995.  
  996.                         index >>= 4;
  997.                 }
  998.         }
  999. }
  1000.  
  1001. //
  1002. //----------------------------------------------------------------------------------------------------------
  1003. void CAIProxy::QueryWeaponInfo(SAIWeaponInfo& weaponInfo)
  1004. {
  1005.         EntityId currentWeaponId = 0;
  1006.         IWeapon* pWeapon(QueryCurrentWeapon(currentWeaponId));
  1007.         if (!pWeapon)
  1008.                 return;
  1009.  
  1010.         weaponInfo.canMelee = pWeapon->CanMeleeAttack();
  1011.         weaponInfo.outOfAmmo = pWeapon->OutOfAmmo(false);
  1012.         weaponInfo.lowAmmo = pWeapon->LowAmmo(0.15f);
  1013.         weaponInfo.shotIsDone = m_WeaponShotIsDone;
  1014.         weaponInfo.lastShotTime = m_lastShotTime;
  1015.  
  1016. #ifdef AI_G4
  1017.         weaponInfo.hasLightAccessory = weaponInfo.hasLaserAccessory = false;
  1018.         weaponInfo.hasLightAccessory = weaponInfo.hasLightAccessory = false;
  1019. #else
  1020.         weaponInfo.hasLaserAccessory = pWeapon->Query(eWQ_Has_Accessory_Laser);
  1021.         weaponInfo.hasLightAccessory = pWeapon->Query(eWQ_Has_Accessory_Flashlight);
  1022. #endif
  1023.  
  1024.         if (IFireMode* pFireMode = pWeapon->GetFireMode(pWeapon->GetCurrentFireMode()))
  1025.         {
  1026.                 weaponInfo.ammoCount = pFireMode->GetAmmoCount();
  1027.                 weaponInfo.clipSize = pFireMode->GetClipSize();
  1028.                 weaponInfo.isReloading = pFireMode ? pFireMode->IsReloading() : false;
  1029.                 weaponInfo.isFiring = pFireMode ? pFireMode->IsFiring() : false;
  1030.         }
  1031. }
  1032.  
  1033. //
  1034. //----------------------------------------------------------------------------------------------------------
  1035. void CAIProxy::UpdateCurrentWeapon()
  1036. {
  1037.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  1038.  
  1039.         IWeapon* pCurrentWeapon = NULL;
  1040.         EntityId currentWeaponId = 0;
  1041.         m_CurrentWeaponCanFire = true;
  1042.  
  1043.         IItemSystem* pItemSystem = CCryAction::GetCryAction()->GetIItemSystem();
  1044.         //assert(pItemSystem);
  1045.  
  1046.         IActor* pActor = GetActor();
  1047.         if (pActor)
  1048.         {
  1049.                 IItem* pItem = NULL;
  1050.  
  1051.                 if (IVehicle* pVehicle = pActor->GetLinkedVehicle())
  1052.                 {
  1053.                         // mounted weapon( gunner seat )
  1054.                         SVehicleWeaponInfo weaponInfo;
  1055.                         if (pVehicle->GetCurrentWeaponInfo(weaponInfo, m_pGameObject->GetEntityId(), m_UseSecondaryVehicleWeapon))
  1056.                         {
  1057.                                 pItem = CCryAction::GetCryAction()->GetIItemSystem()->GetItem(weaponInfo.entityId);
  1058.                                 m_CurrentWeaponCanFire = weaponInfo.bCanFire;
  1059.                         }
  1060.                 }
  1061.                 else
  1062.                 {
  1063.                         pItem = pActor->GetCurrentItem();
  1064.                 }
  1065.  
  1066.                 pCurrentWeapon = pItem ? pItem->GetIWeapon() : NULL;
  1067.                 currentWeaponId = (pCurrentWeapon ? pItem->GetEntityId() : 0);
  1068.         }
  1069.  
  1070.         bool updateCachedWeaponDescriptor = false;
  1071.  
  1072.         const bool weaponChanged = m_currentWeaponId != currentWeaponId;
  1073.         if (weaponChanged)
  1074.         {
  1075.                 updateCachedWeaponDescriptor = true;
  1076.  
  1077.                 IItem* pOldItem = pItemSystem->GetItem(m_currentWeaponId);
  1078.                 IWeapon* pOldWeapon = pOldItem ? pOldItem->GetIWeapon() : NULL;
  1079.                 if (pOldWeapon)
  1080.                         pOldWeapon->StopFire();
  1081.  
  1082.                 m_currentWeaponId = currentWeaponId;
  1083.         }
  1084.         else
  1085.         {
  1086.                 const int currentWeaponFiremodeIndex = pCurrentWeapon ? pCurrentWeapon->GetCurrentFireMode() : -1;
  1087.                 const bool fireModeChanged = (m_currentWeaponFiremodeIndex != currentWeaponFiremodeIndex);
  1088.                 if (fireModeChanged)
  1089.                 {
  1090.                         updateCachedWeaponDescriptor = true;
  1091.                         m_currentWeaponFiremodeIndex = currentWeaponFiremodeIndex;
  1092.                 }
  1093.         }
  1094.  
  1095.         if (updateCachedWeaponDescriptor)
  1096.         {
  1097.                 m_currentWeaponDescriptor = pCurrentWeapon ? pCurrentWeapon->GetAIWeaponDescriptor() : AIWeaponDescriptor();
  1098.         }
  1099. }
  1100.  
  1101. //
  1102. //----------------------------------------------------------------------------------------------------------
  1103. void CAIProxy::EnableWeaponListener(const EntityId weaponId, bool needsSignal)
  1104. {
  1105.         m_shotBulletCount = 0;
  1106.         m_lastShotTime.SetSeconds(0.0f);
  1107.         m_NeedsShootSignal = needsSignal;
  1108.  
  1109.         if (IWeapon* pWeapon = GetWeaponFromId(weaponId))
  1110.         {
  1111.                 if (m_weaponListenerId != 0)
  1112.                 {
  1113.                         RemoveWeaponListener(GetWeaponFromId(m_weaponListenerId));
  1114.                 }
  1115.  
  1116.                 pWeapon->AddEventListener(this, __FUNCTION__);
  1117.                 m_weaponListenerId = weaponId;
  1118.         }
  1119. }
  1120.  
  1121. //
  1122. //----------------------------------------------------------------------------------------------------------
  1123. void CAIProxy::OnShoot(IWeapon* pWeapon, EntityId shooterId, EntityId ammoId, IEntityClass* pAmmoType,
  1124.                        const Vec3& pos, const Vec3& dir, const Vec3& vel)
  1125. {
  1126.         IEntity* pEntity = m_pGameObject->GetEntity();
  1127.         if (!pEntity)
  1128.         {
  1129.                 AIWarningID(">> ", "CAIProxy::OnShoot null entity");
  1130.                 return;
  1131.         }
  1132.  
  1133.         //    if (pEntity->GetAI() && pEntity->GetAI()->GetAIType() != AIOBJECT_PLAYER)
  1134.         //      gEnv->pAISystem->DebugDrawFakeTracer(pos, dir);
  1135.  
  1136.         m_shotBulletCount++;
  1137.         m_lastShotTime = gEnv->pTimer->GetFrameStartTime();
  1138.  
  1139.         m_WeaponShotIsDone = true;
  1140.         IPuppet* pPuppet = CastToIPuppetSafe(pEntity->GetAI());
  1141.         if (pPuppet && pPuppet->GetFirecommandHandler())
  1142.                 pPuppet->GetFirecommandHandler()->OnShoot();
  1143.  
  1144.         if (!m_NeedsShootSignal)
  1145.                 return;
  1146.         SendSignal(0, "WPN_SHOOT", pEntity, NULL);
  1147. }
  1148.  
  1149. //
  1150. //----------------------------------------------------------------------------------------------------------
  1151. void CAIProxy::OnDropped(IWeapon* pWeapon, EntityId actorId)
  1152. {
  1153.         m_NeedsShootSignal = false;
  1154.         RemoveWeaponListener(pWeapon);
  1155. }
  1156.  
  1157. //
  1158. //----------------------------------------------------------------------------------------------------------
  1159. void CAIProxy::OnMelee(IWeapon* pWeapon, EntityId shooterId)
  1160. {
  1161.         IEntity* pEntity = m_pGameObject->GetEntity();
  1162.         assert(pEntity);
  1163.         if (pEntity)
  1164.                 SendSignal(0, "WPN_MELEE", pEntity, NULL);
  1165. }
  1166.  
  1167. //
  1168. //----------------------------------------------------------------------------------------------------------
  1169. void CAIProxy::OnSelected(IWeapon* pWeapon, bool selected)
  1170. {
  1171.         if (!selected)
  1172.         {
  1173.                 m_NeedsShootSignal = false;
  1174.                 RemoveWeaponListener(pWeapon);
  1175.         }
  1176. }
  1177. //----------------------------------------------------------------------------------------------------------
  1178. void CAIProxy::OnEndBurst(IWeapon* pWeapon, EntityId actorId)
  1179. {
  1180.         IEntity* pEntity = m_pGameObject->GetEntity();
  1181.         assert(pEntity);
  1182.         if (!pEntity)
  1183.         {
  1184.                 AIWarningID(">> ", "CAIProxy::OnEndBurst null entity");
  1185.                 return;
  1186.         }
  1187.         SendSignal(0, "WPN_END_BURST", pEntity, NULL);
  1188. }
  1189.  
  1190. //
  1191. //----------------------------------------------------------------------------------------------------------
  1192. IPhysicalEntity* CAIProxy::GetPhysics(bool wantCharacterPhysics)
  1193. {
  1194.         if (wantCharacterPhysics)
  1195.         {
  1196.                 ICharacterInstance* pCharacter(m_pGameObject->GetEntity()->GetCharacter(0));
  1197.                 if (pCharacter)
  1198.                         return pCharacter->GetISkeletonPose()->GetCharacterPhysics();
  1199.                 return NULL;
  1200.         }
  1201.         return m_pGameObject->GetEntity()->GetPhysics();
  1202. }
  1203.  
  1204. //
  1205. //----------------------------------------------------------------------------------------------------------
  1206. void CAIProxy::DebugDraw(int iParam)
  1207. {
  1208.         if (!m_pAIHandler)
  1209.                 return;
  1210.  
  1211.         IAIDebugRenderer* pDebugRenderer = gEnv->pAISystem->GetAIDebugRenderer();
  1212.  
  1213.         if (iParam == 1)
  1214.         {
  1215.                 // Stats target drawing.
  1216.                 pDebugRenderer->TextToScreenColor(50, 66, 0.3f, 0.3f, 0.3f, 1.f, "- Proxy Information --");
  1217.  
  1218.                 const char* szCurrentBehaviour = 0;
  1219.                 const char* szPreviousBehaviour = 0;
  1220.                 const char* szFirstBehaviour = 0;
  1221.  
  1222.                 if (m_pAIHandler->m_pBehavior.GetPtr())
  1223.                         m_pAIHandler->m_pBehavior->GetValue("name", szCurrentBehaviour) || m_pAIHandler->m_pBehavior->GetValue("Name", szCurrentBehaviour);
  1224.  
  1225.                 if (m_pAIHandler->m_pPreviousBehavior.GetPtr())
  1226.                         m_pAIHandler->m_pPreviousBehavior->GetValue("name", szCurrentBehaviour) || m_pAIHandler->m_pPreviousBehavior->GetValue("Name", szCurrentBehaviour);
  1227.  
  1228.                 if (!m_pAIHandler->m_sFirstBehaviorName.empty())
  1229.                         szFirstBehaviour = m_pAIHandler->m_sFirstBehaviorName.c_str();
  1230.  
  1231.                 pDebugRenderer->TextToScreen(50, 74, "BEHAVIOUR: %s", szCurrentBehaviour);
  1232.                 pDebugRenderer->TextToScreen(50, 76, " PREVIOUS BEHAVIOUR: %s", szPreviousBehaviour);
  1233.                 pDebugRenderer->TextToScreen(50, 78, " DESIGNER ASSIGNED BEHAVIOUR: %s", szFirstBehaviour);
  1234.  
  1235. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  1236.                 const char* szCurrentCharacter = m_pAIHandler->m_sCharacterName.c_str();
  1237.                 const char* szPreviousCharacter = m_pAIHandler->m_sPrevCharacterName.c_str();
  1238.                 const char* szFirstCharacter = m_pAIHandler->m_sFirstCharacterName.c_str();
  1239.  
  1240.                 pDebugRenderer->TextToScreen(50, 82, "CHARACTER: %s", szCurrentCharacter);
  1241.                 pDebugRenderer->TextToScreen(50, 84, " PREVIOUS CHARACTER: %s", szPreviousCharacter);
  1242.                 pDebugRenderer->TextToScreen(50, 86, " DESIGNER ASSIGNED CHARACTER: %s", szFirstCharacter);
  1243. #endif
  1244.  
  1245.                 if (m_pAIHandler)
  1246.                 {
  1247.                         const char* szEPMsg = " - ";
  1248.                         switch (GetActorTargetPhase())
  1249.                         {
  1250.                         //                      case eATP_Cancel: szEPMsg = "Cancel"; break;
  1251.                         case eATP_None:
  1252.                                 szEPMsg = " - ";
  1253.                                 break;
  1254.                         //                      case eATP_Request: szEPMsg = "Request"; break;
  1255.                         case eATP_Waiting:
  1256.                                 szEPMsg = "Waiting";
  1257.                                 break;
  1258.                         case eATP_Starting:
  1259.                                 szEPMsg = "Starting";
  1260.                                 break;
  1261.                         case eATP_Started:
  1262.                                 szEPMsg = "Started";
  1263.                                 break;
  1264.                         case eATP_Playing:
  1265.                                 szEPMsg = "Playing";
  1266.                                 break;
  1267.                         case eATP_StartedAndFinished:
  1268.                                 szEPMsg = "Started/Finished";
  1269.                                 break;
  1270.                         case eATP_Finished:
  1271.                                 szEPMsg = "Finished";
  1272.                                 break;
  1273.                         case eATP_Error:
  1274.                                 szEPMsg = "Error";
  1275.                                 break;
  1276.                         }
  1277.  
  1278.                         pDebugRenderer->TextToScreen(50, 90, "ANIMATION: %s", IsAnimationBlockingMovement() ? "MOVEMENT BLOCKED!" : "");
  1279.                         pDebugRenderer->TextToScreen(50, 92, "           ExactPos:%s", szEPMsg);
  1280.                 }
  1281.         }
  1282. }
  1283.  
  1284. //
  1285. //----------------------------------------------------------------------------------------------------------
  1286. void CAIProxy::Reset(EObjectResetType type)
  1287. {
  1288.         ReloadScriptProperties();
  1289.  
  1290.         m_forcedExecute = 0;
  1291.         EnableUpdate(type == AIOBJRESET_INIT);
  1292.         m_shotBulletCount = 0;
  1293.         m_lastShotTime.SetSeconds(0.0f);
  1294.  
  1295.         m_CurrentWeaponCanFire = true;
  1296.         m_UseSecondaryVehicleWeapon = false;
  1297.  
  1298.         m_currentWeaponId = 0;
  1299.         m_currentWeaponFiremodeIndex = std::numeric_limits<int>::max();
  1300.         m_currentWeaponDescriptor = AIWeaponDescriptor();
  1301.  
  1302.         //if (gEnv->IsEditor())
  1303.         if (m_pGameObject)
  1304.                 m_pGameObject->SetAIActivation(eGOAIAM_VisibleOrInRange); // we suppose the first update will set this properly.
  1305.  
  1306.         if (m_commHandler.get())
  1307.                 m_commHandler->Reset();
  1308.  
  1309.         if (m_pAIHandler)
  1310.                 m_pAIHandler->Reset(type);
  1311.  
  1312.         // Notify signaler handlers
  1313.         CRY_ASSERT(m_pGameObject);
  1314.         if (m_pGameObject)
  1315.         {
  1316.                 IMovementController* pMC = m_pGameObject->GetMovementController();
  1317.                 if (pMC)
  1318.                 {
  1319.                         CMovementRequest mr;
  1320.                         mr.SetAlertness(0);
  1321.  
  1322.                         // [DAVID] Clear Actor/AC alertness
  1323.                         IActor* pActor = GetActor();
  1324.                         if (pActor != NULL)
  1325.                                 pActor->SetFacialAlertnessLevel(0);
  1326.  
  1327.                         mr.ClearLookTarget();
  1328.                         mr.ClearActorTarget();
  1329.                         mr.ClearLean();
  1330.                         mr.ClearPeekOver();
  1331.                         mr.ClearPrediction();
  1332.                         // try, and retry once
  1333.                         if (!pMC->RequestMovement(mr))
  1334.                                 pMC->RequestMovement(mr);
  1335.                 }
  1336.  
  1337.                 CCryAction::GetCryAction()->GetRangeSignaling()->OnProxyReset(m_pGameObject->GetEntityId());
  1338.                 CCryAction::GetCryAction()->GetSignalTimer()->OnProxyReset(m_pGameObject->GetEntityId());
  1339.         }
  1340.  
  1341.         m_aimQueryMode = QueryAimFromMovementController;
  1342. }
  1343.  
  1344. IAICommunicationHandler* CAIProxy::GetCommunicationHandler()
  1345. {
  1346.         return m_commHandler.get();
  1347. }
  1348.  
  1349. bool CAIProxy::BecomeAggressiveToAgent(EntityId agentID)
  1350. {
  1351.         if (IActor* pActor = GetActor())
  1352.                 return pActor->BecomeAggressiveToAgent(agentID);
  1353.         else
  1354.                 return false;
  1355. }
  1356.  
  1357. void CAIProxy::SetForcedExecute(bool forced)
  1358. {
  1359.         m_forcedExecute += forced ? 1 : -1;
  1360.         assert(m_forcedExecute >= 0); // Below zero? More disables then enables!
  1361.         assert(m_forcedExecute < 16); // Just a little sanity check
  1362.  
  1363.         if (IEntity* pEntity = m_pGameObject->GetEntity())
  1364.         {
  1365.                 IAIActor* pAIActor = CastToIAIActorSafe(pEntity->GetAI());
  1366.                 if (pAIActor)
  1367.                 {
  1368.                         if (forced)
  1369.                                 pAIActor->SetSignal(10, "OnForcedExecute", pEntity);
  1370.                         else if (m_forcedExecute <= 0)
  1371.                                 pAIActor->SetSignal(10, "OnForcedExecuteComplete", pEntity);
  1372.                 }
  1373.         }
  1374. }
  1375.  
  1376. bool CAIProxy::IsForcedExecute() const
  1377. {
  1378.         return m_forcedExecute > 0;
  1379. }
  1380.  
  1381. //
  1382. //----------------------------------------------------------------------------------------------------------
  1383. CTimeValue CAIProxy::GetEstimatedAGAnimationLength(EAIAGInput input, const char* value)
  1384. {
  1385.         if (m_pAIHandler)
  1386.                 return m_pAIHandler->GetEstimatedAGAnimationLength(input, value);
  1387.         else
  1388.                 return CTimeValue();
  1389. }
  1390.  
  1391. //
  1392. //----------------------------------------------------------------------------------------------------------
  1393. bool CAIProxy::SetAGInput(EAIAGInput input, const char* value, const bool isUrgent)
  1394. {
  1395.         return (m_pAIHandler ? m_pAIHandler->SetAGInput(input, value, isUrgent) : false);
  1396. }
  1397.  
  1398. //
  1399. //----------------------------------------------------------------------------------------------------------
  1400. bool CAIProxy::ResetAGInput(EAIAGInput input)
  1401. {
  1402.         return (m_pAIHandler ? m_pAIHandler->ResetAGInput(input) : false);
  1403. }
  1404.  
  1405. //
  1406. //----------------------------------------------------------------------------------------------------------
  1407. bool CAIProxy::IsSignalAnimationPlayed(const char* value)
  1408. {
  1409.         return (m_pAIHandler ? m_pAIHandler->IsSignalAnimationPlayed(value) : true);
  1410. }
  1411.  
  1412. //
  1413. //----------------------------------------------------------------------------------------------------------
  1414. bool CAIProxy::IsActionAnimationStarted(const char* value)
  1415. {
  1416.         return (m_pAIHandler ? m_pAIHandler->IsActionAnimationStarted(value) : true);
  1417. }
  1418.  
  1419. //
  1420. //----------------------------------------------------------------------------------------------------------
  1421. bool CAIProxy::IsAnimationBlockingMovement() const
  1422. {
  1423.         bool blocking = false;
  1424.  
  1425.         if (m_pAIHandler)
  1426.                 blocking |= m_pAIHandler->IsAnimationBlockingMovement();
  1427.  
  1428.         if (m_commHandler.get() && m_commHandler->IsPlayingAnimation())
  1429.         {
  1430.                 IActor* pActor = const_cast<IActor*>(GetActor());
  1431.                 if (pActor)
  1432.                 {
  1433.                         const IAnimatedCharacter* pAnimChar = pActor->GetAnimatedCharacter();
  1434.                         blocking |= pAnimChar && ((pAnimChar->GetMCMH() == eMCM_Animation) || (pAnimChar->GetMCMH() == eMCM_AnimationHCollision));
  1435.                 }
  1436.         }
  1437.  
  1438.         return blocking;
  1439. }
  1440.  
  1441. //
  1442. //----------------------------------------------------------------------------------------------------------
  1443. EActorTargetPhase CAIProxy::GetActorTargetPhase() const
  1444. {
  1445.         return (m_pAIHandler ? m_pAIHandler->GetActorTargetPhase() : eATP_None);
  1446. }
  1447.  
  1448. //
  1449. //----------------------------------------------------------------------------------------------------------
  1450. void CAIProxy::PlayAnimationAction(const IAIAction* pAction, int goalPipeId)
  1451. {
  1452.         CRY_ASSERT(pAction->GetAnimationName() != NULL && pAction->GetAnimationName()[0] != 0);
  1453.  
  1454.         if (m_animActionGoalPipeId != 0)
  1455.                 gEnv->pAISystem->GetAIActionManager()->AbortAIAction(m_pGameObject->GetEntity(), m_animActionGoalPipeId);
  1456.         m_animActionGoalPipeId = goalPipeId;
  1457.  
  1458.         IActor* pActor = GetActor();
  1459.         if (pActor != NULL)
  1460.         {
  1461.                 if (pAction->IsExactPositioning())
  1462.                         pActor->PlayExactPositioningAnimation(pAction->GetAnimationName(), pAction->IsSignaledAnimation(), pAction->GetAnimationPos(),
  1463.                                                               pAction->GetAnimationDir(), pAction->GetStartWidth(), pAction->GetStartArcAngle(), DEG2RAD(pAction->GetDirectionTolerance()));
  1464.                 else
  1465.                         pActor->PlayAnimation(pAction->GetAnimationName(), pAction->IsSignaledAnimation());
  1466.         }
  1467. }
  1468.  
  1469. //
  1470. //----------------------------------------------------------------------------------------------------------
  1471. void CAIProxy::AnimationActionDone(bool succeeded)
  1472. {
  1473.         if (m_animActionGoalPipeId)
  1474.         {
  1475.                 int tmp = m_animActionGoalPipeId;
  1476.                 m_animActionGoalPipeId = 0;
  1477.                 if (succeeded)
  1478.                         gEnv->pAISystem->GetAIActionManager()->FinishAIAction(m_pGameObject->GetEntity(), tmp);
  1479.                 else
  1480.                         gEnv->pAISystem->GetAIActionManager()->AbortAIAction(m_pGameObject->GetEntity(), tmp);
  1481.         }
  1482. }
  1483.  
  1484. bool CAIProxy::IsPlayingSmartObjectAction() const
  1485. {
  1486.         bool bResult = false;
  1487.  
  1488.         // TODO: Users should probably query the IPipeUser directly
  1489.         if (IEntity* pEntity = m_pGameObject->GetEntity())
  1490.         {
  1491.                 if (IAIObject* pAIObject = pEntity->GetAI())
  1492.                 {
  1493.                         if (IPipeUser* pPipeUser = pAIObject->CastToIPipeUser())
  1494.                         {
  1495.                                 bResult = pPipeUser->IsUsingNavSO();
  1496.                         }
  1497.                 }
  1498.         }
  1499.  
  1500.         return bResult;
  1501. }
  1502.  
  1503. //
  1504. //----------------------------------------------------------------------------------------------------------
  1505. void CAIProxy::UpdateMind(SOBJECTSTATE& state)
  1506. {
  1507.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  1508.  
  1509.         UpdateCurrentWeapon();
  1510.  
  1511.         // (MATT) Run delayed constructors on behaviour and character and update face {2008/09/05}
  1512.         if (m_pAIHandler)
  1513.                 m_pAIHandler->Update();
  1514.  
  1515.         // (MATT) For signals that should wait until next update, mainly used by Troopers {2008/09/05}
  1516.         std::vector<AISIGNAL> nextUpdateSignals;
  1517.  
  1518.         if (m_pGameObject->GetEntity()->GetAI()->IsUpdatedOnce())
  1519.         {
  1520.                 while (!state.vSignals.empty())
  1521.                 {
  1522.                         AISIGNAL sstruct = state.vSignals.front();
  1523.                         state.vSignals.erase(0);
  1524.  
  1525.                         int signal = sstruct.nSignal;
  1526.                         if (signal == AISIGNAL_PROCESS_NEXT_UPDATE)
  1527.                         {
  1528.                                 sstruct.nSignal = AISIGNAL_RECEIVED_PREV_UPDATE;
  1529.                                 nextUpdateSignals.push_back(sstruct);
  1530.                         }
  1531.                         else
  1532.                         {
  1533.                                 const char* szText = sstruct.strText;
  1534.                                 const uint32 crc = sstruct.m_nCrcText;
  1535.                                 IEntity* pSender = gEnv->pEntitySystem->GetEntity(sstruct.senderID);
  1536.                                 SendSignal(signal, szText, pSender, sstruct.pEData, sstruct.m_nCrcText);
  1537.  
  1538.                                 if (sstruct.pEData)
  1539.                                         gEnv->pAISystem->FreeSignalExtraData(sstruct.pEData);
  1540.                         }
  1541.                 }
  1542.  
  1543.                 std::vector<AISIGNAL>::iterator it = nextUpdateSignals.begin(), itEnd = nextUpdateSignals.end();
  1544.                 for (; it != itEnd; ++it)
  1545.                         state.vSignals.push_back(*it);
  1546.         }
  1547.         else
  1548.         {
  1549.                 // (MATT) Process init signals before first update - is this really needed? {2008/09/05}
  1550.                 int size = state.vSignals.size();
  1551.                 int i = 0;
  1552.                 while (i < size)
  1553.                 {
  1554.                         AISIGNAL signal = state.vSignals[i];
  1555.  
  1556.                         if (signal.nSignal == AISIGNAL_INITIALIZATION)
  1557.                         {
  1558.                                 state.vSignals.erase(state.vSignals.begin() + i);
  1559.                                 gEnv->pLog->LogError("Initialisation signal used \"%s\"", signal.strText);
  1560.  
  1561.                                 // process only init. signals!
  1562.                                 IEntity* pSender = gEnv->pEntitySystem->GetEntity(signal.senderID);
  1563.                                 SendSignal(signal.nSignal, signal.strText, pSender, signal.pEData);
  1564.                                 if (signal.pEData)
  1565.                                         gEnv->pAISystem->FreeSignalExtraData(signal.pEData);
  1566.  
  1567.                                 // TO DO: check if this is still necessary once the newly inserted signals will be processed on the next update
  1568.                                 if (--size != state.vSignals.size())
  1569.                                 {
  1570.                                         // a new signal was inserted while processing this one
  1571.                                         // so, let's start over
  1572.                                         size = state.vSignals.size();
  1573.                                 }
  1574.                         }
  1575.                         else
  1576.                                 i++;
  1577.                 }
  1578.         }
  1579.  
  1580.         if (!m_pAIHandler)
  1581.                 return;
  1582.  
  1583.         m_pAIHandler->AIMind(state);
  1584. }
  1585.  
  1586. //
  1587. //----------------------------------------------------------------------------------------------------------
  1588. void CAIProxy::OnReused(IEntity* pEntity, SEntitySpawnParams& params)
  1589. {
  1590.         m_pGameObject = CCryAction::GetCryAction()->GetGameObject(params.id);
  1591.         m_pIActor = gEnv->pGameFramework->GetIActorSystem()->GetActor(params.id);
  1592.  
  1593.         EnableUpdate(false);
  1594.  
  1595.         ReloadScriptProperties();
  1596.  
  1597.         if (m_commHandler.get())
  1598.                 m_commHandler->OnReused(pEntity);
  1599.  
  1600.         // Reuse the handler
  1601.         if (m_pAIHandler)
  1602.                 m_pAIHandler->OnReused(m_pGameObject);
  1603.  
  1604.         // Reset the AI - this will also reset the AIProxy later
  1605.         IAIObject* pAI = pEntity->GetAI();
  1606.         if (pAI)
  1607.         {
  1608.                 /*pAI->SetEntityID(params.id);
  1609.                    pAI->SetName(pEntity->GetName());*/
  1610.                 pAI->Reset(AIOBJRESET_INIT);
  1611.         }
  1612.  
  1613.         if (m_weaponListenerId != 0)
  1614.         {
  1615.                 RemoveWeaponListener(GetWeaponFromId(m_weaponListenerId));
  1616.         }
  1617. }
  1618.  
  1619. //
  1620. //----------------------------------------------------------------------------------------------------------
  1621. void CAIProxy::ReloadScriptProperties()
  1622. {
  1623.         if (IScriptTable* script = m_pGameObject->GetEntity()->GetScriptTable())
  1624.         {
  1625.                 SmartScriptTable props;
  1626.                 if (script->GetValue("Properties", props))
  1627.                 {
  1628.                         const char* voice;
  1629.                         if (props->GetValue("esVoice", voice))
  1630.                         {
  1631.                                 m_voiceLibrary = voice;
  1632.                                 CreateTestVoiceLibraryNameFromBasicName(m_voiceLibrary, m_voiceLibraryWhenForcingTest);
  1633.                         }
  1634.  
  1635.                         const char* commConfigName;
  1636.                         if (props->GetValue("esCommConfig", commConfigName))
  1637.                                 m_commConfigName = commConfigName;
  1638.  
  1639.                         props->GetValue("fFmodCharacterTypeParam", m_FmodCharacterTypeParam);
  1640.  
  1641.                         const char* behaviorSelectionTreeName;
  1642.                         if (props->GetValue("esBehaviorSelectionTree", behaviorSelectionTreeName)
  1643.                             && stricmp(behaviorSelectionTreeName, "None"))
  1644.                                 m_behaviorSelectionTreeName = behaviorSelectionTreeName;
  1645.  
  1646.                         const char* agentTypeName;
  1647.                         if (props->GetValue("esNavigationType", agentTypeName)
  1648.                             && *agentTypeName)
  1649.                                 m_agentTypeName = agentTypeName;
  1650.                 }
  1651.                 SmartScriptTable instanceProps;
  1652.                 if (script->GetValue("PropertiesInstance", instanceProps))
  1653.                 {
  1654.                         // Check if some properties are overridden in the instance
  1655.                         const char* voice;
  1656.                         if (instanceProps->GetValue("esVoice", voice) && strcmp(voice, "") != 0)
  1657.                         {
  1658.                                 m_voiceLibrary = voice;
  1659.                                 CreateTestVoiceLibraryNameFromBasicName(m_voiceLibrary, m_voiceLibraryWhenForcingTest);
  1660.                         }
  1661.                 }
  1662.         }
  1663. }
  1664.  
  1665. //
  1666. //----------------------------------------------------------------------------------------------------------
  1667. IActor* CAIProxy::GetActor() const
  1668. {
  1669.         if (!m_pIActor)
  1670.                 m_pIActor = gEnv->pGameFramework->GetIActorSystem()->GetActor(m_pGameObject->GetEntityId());
  1671.         return m_pIActor;
  1672. }
  1673.  
  1674. //
  1675. //----------------------------------------------------------------------------------------------------------
  1676. void CAIProxy::SendSignal(int signalID, const char* szText, IEntity* pSender, const IAISignalExtraData* pData, uint32 crc /* = 0u */)
  1677. {
  1678.         IF_UNLIKELY (crc == 0u)
  1679.         {
  1680.                 crc = CCrc32::Compute(szText);
  1681.         }
  1682.  
  1683.         if (m_pAIHandler)
  1684.         {
  1685.                 m_pAIHandler->AISignal(signalID, szText, crc, pSender, pData);
  1686.         }
  1687. }
  1688.  
  1689. //
  1690. // gets the corners of the tightest projected bounding rectangle in 2D world space coordinates
  1691. //----------------------------------------------------------------------------------------------------------
  1692. void CAIProxy::GetWorldBoundingRect(Vec3& FL, Vec3& FR, Vec3& BL, Vec3& BR, float extra) const
  1693. {
  1694.         const Vec3 pos = m_pGameObject->GetEntity()->GetWorldPos();
  1695.         const Quat& quat = m_pGameObject->GetEntity()->GetRotation();
  1696.         Vec3 dir = quat * Vec3(0, 1, 0);
  1697.         dir.z = 0.0f;
  1698.         dir.NormalizeSafe();
  1699.  
  1700.         const Vec3 sideDir(dir.y, -dir.x, 0.0f);
  1701.  
  1702.         IEntityRender* pIEntityRender = m_pGameObject->GetEntity()->GetRenderInterface();
  1703.         AABB bounds;
  1704.         pIEntityRender->GetLocalBounds(bounds);
  1705.  
  1706.         bounds.max.x += extra;
  1707.         bounds.max.y += extra;
  1708.         bounds.min.x -= extra;
  1709.         bounds.min.y -= extra;
  1710.  
  1711.         FL = pos + bounds.max.y * dir + bounds.min.x * sideDir;
  1712.         FR = pos + bounds.max.y * dir + bounds.max.x * sideDir;
  1713.         BL = pos + bounds.min.y * dir + bounds.min.x * sideDir;
  1714.         BR = pos + bounds.min.y * dir + bounds.max.x * sideDir;
  1715. }
  1716.  
  1717. //
  1718. //----------------------------------------------------------------------------------------------------------
  1719. int CAIProxy::GetAlertnessState() const
  1720. {
  1721.         return m_pAIHandler ? m_pAIHandler->m_CurrentAlertness : 0;
  1722. }
  1723.  
  1724. //
  1725. //----------------------------------------------------------------------------------------------------------
  1726. void CAIProxy::SetAlertnessState(int alertness)
  1727. {
  1728.         if (m_pAIHandler)
  1729.                 m_pAIHandler->SetAlertness(alertness);
  1730. }
  1731.  
  1732. //
  1733. //----------------------------------------------------------------------------------------------------------
  1734. bool CAIProxy::IsCurrentBehaviorExclusive() const
  1735. {
  1736.         if (!m_pAIHandler)
  1737.                 return false;
  1738.         return m_pAIHandler->m_CurrentExclusive;
  1739. }
  1740.  
  1741. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  1742. //
  1743. //----------------------------------------------------------------------------------------------------------
  1744. bool CAIProxy::SetCharacter(const char* character, const char* behavior)
  1745. {
  1746.         if (!m_pAIHandler)
  1747.                 return true;
  1748.         bool ret = m_pAIHandler->SetCharacter(character);
  1749.         if (behavior)
  1750.                 m_pAIHandler->SetBehavior(behavior);
  1751.         return ret;
  1752. }
  1753.  
  1754. //
  1755. //----------------------------------------------------------------------------------------------------------
  1756. const char* CAIProxy::GetCharacter()
  1757. {
  1758.         if (!m_pAIHandler)
  1759.                 return 0;
  1760.         return m_pAIHandler->GetCharacter();
  1761. }
  1762. #endif
  1763.  
  1764. //
  1765. //----------------------------------------------------------------------------------------------------------
  1766. void CAIProxy::GetReadabilityBlockingParams(const char* text, float& time, int& id)
  1767. {
  1768.         time = 0;
  1769.         id = 0;
  1770. }
  1771.  
  1772. //
  1773. //----------------------------------------------------------------------------------------------------------
  1774. void CAIProxy::Serialize(TSerialize ser)
  1775. {
  1776.         if (ser.IsReading())
  1777.         {
  1778.                 m_pIActor = 0; // forces re-caching in QueryBodyInfo
  1779.  
  1780.                 if (!m_pAIHandler)
  1781.                 {
  1782.                         m_pAIHandler = new CAIHandler(m_pGameObject);
  1783.                         m_pAIHandler->Init();
  1784.                 }
  1785.         }
  1786.  
  1787.         CRY_ASSERT(m_pAIHandler);
  1788.  
  1789.         ser.BeginGroup("AIProxy");
  1790.  
  1791.         m_pAIHandler->Serialize(ser);
  1792.         ser.Value("m_firing", m_firing);
  1793.         ser.Value("m_firingSecondary", m_firingSecondary);
  1794.         ser.Value("m_forcedExecute", m_forcedExecute);
  1795.  
  1796.         if (ser.IsReading())
  1797.         {
  1798.                 m_currentWeaponId = 0;
  1799.                 UpdateCurrentWeapon();
  1800.         }
  1801.  
  1802.         ser.EnumValue("m_aimQueryMode", m_aimQueryMode, FirstAimQueryMode, AimQueryModeCount);
  1803.         ser.Value("m_fMinFireTime", m_fMinFireTime);
  1804.         ser.Value("m_WeaponShotIsDone", m_WeaponShotIsDone);
  1805.         ser.Value("m_NeedsShootSignal", m_NeedsShootSignal);
  1806.         ser.Value("m_IsDisabled", m_IsDisabled);
  1807.         ser.Value("m_UpdateAlways", m_UpdateAlways);
  1808.         ser.Value("m_lastShotTime", m_lastShotTime);
  1809.         ser.Value("m_shotBulletCount", m_shotBulletCount);
  1810.         ser.Value("m_CurrentWeaponCanFire", m_CurrentWeaponCanFire);
  1811.         ser.Value("m_UseSecondaryVehicleWeapon", m_UseSecondaryVehicleWeapon);
  1812.         ser.Value("m_autoDeactivated", m_autoDeactivated);
  1813.  
  1814.         ser.EndGroup();
  1815. }
  1816.  
  1817. //
  1818. //---------------------------------------------------------------------------------------------------------------
  1819. bool CAIProxy::PredictProjectileHit(float vel, Vec3& posOut, Vec3& dirOut, float& speedOut, Vec3* pTrajectoryPositions, unsigned int* trajectorySizeInOut, Vec3* pTrajectoryVelocities)
  1820. {
  1821.         EntityId currentWeaponId = 0;
  1822.         IWeapon* pCurrentWeapon = GetCurrentWeapon(currentWeaponId);
  1823.         if (!pCurrentWeapon)
  1824.                 return false;
  1825.  
  1826.         SAIBodyInfo bodyInfo;
  1827.         QueryBodyInfo(bodyInfo);
  1828.  
  1829.         return pCurrentWeapon->PredictProjectileHit(GetPhysics(), bodyInfo.vFirePos, dirOut, Vec3(0, 0, 0), vel,
  1830.                                                     posOut, speedOut, pTrajectoryPositions, trajectorySizeInOut, 0.24f, pTrajectoryVelocities, true);
  1831. }
  1832.  
  1833. //
  1834. //---------------------------------------------------------------------------------------------------------------
  1835. bool CAIProxy::PredictProjectileHit(const Vec3& throwDir, float vel, Vec3& posOut, float& speedOut, ERequestedGrenadeType prefGrenadeType,
  1836.                                     Vec3* pTrajectoryPositions, unsigned int* trajectorySizeInOut, Vec3* pTrajectoryVelocities)
  1837. {
  1838.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_GAME);
  1839.  
  1840.         IWeapon* pGrenadeWeapon = GetSecWeapon(prefGrenadeType);
  1841.         if (!pGrenadeWeapon)
  1842.                 return false;
  1843.  
  1844.         SAIBodyInfo bodyInfo;
  1845.         QueryBodyInfo(bodyInfo);
  1846.  
  1847.         return pGrenadeWeapon->PredictProjectileHit(GetPhysics(), bodyInfo.vFirePos, throwDir, Vec3(0, 0, 0), vel,
  1848.                                                     posOut, speedOut, pTrajectoryPositions, trajectorySizeInOut, 0.24f, pTrajectoryVelocities, true);
  1849. }
  1850.  
  1851. //
  1852. //---------------------------------------------------------------------------------------------------------------
  1853. const AIWeaponDescriptor& CAIProxy::GetCurrentWeaponDescriptor() const
  1854. {
  1855.         return m_currentWeaponDescriptor;
  1856. }
  1857.  
  1858. //
  1859. //---------------------------------------------------------------------------------------------------------------
  1860. bool CAIProxy::GetSecWeaponDescriptor(AIWeaponDescriptor& outDescriptor, ERequestedGrenadeType prefGrenadeType) const
  1861. {
  1862.         const IWeapon* pGrenadeWeapon = GetSecWeapon(prefGrenadeType);
  1863.         if (pGrenadeWeapon)
  1864.         {
  1865.                 outDescriptor = pGrenadeWeapon->GetAIWeaponDescriptor();
  1866.                 return true;
  1867.         }
  1868.  
  1869.         return false;
  1870. }
  1871.  
  1872. //
  1873. //---------------------------------------------------------------------------------------------------------------
  1874. void CAIProxy::SetUseSecondaryVehicleWeapon(bool bUseSecondary)
  1875. {
  1876.         if (m_UseSecondaryVehicleWeapon != bUseSecondary)
  1877.         {
  1878.                 m_UseSecondaryVehicleWeapon = bUseSecondary;
  1879.                 UpdateCurrentWeapon();
  1880.         }
  1881. }
  1882.  
  1883. //
  1884. //---------------------------------------------------------------------------------------------------------------
  1885. const char* CAIProxy::GetCurrentBehaviorName() const
  1886. {
  1887.         const char* szName = NULL;
  1888.  
  1889.         if (m_pAIHandler->m_pBehavior.GetPtr())
  1890.         {
  1891.                 m_pAIHandler->m_pBehavior->GetValue("name", szName) || m_pAIHandler->m_pBehavior->GetValue("Name", szName);
  1892.         }
  1893.  
  1894.         return(szName);
  1895. }
  1896.  
  1897. //
  1898. //---------------------------------------------------------------------------------------------------------------
  1899. const char* CAIProxy::GetPreviousBehaviorName() const
  1900. {
  1901.         const char* szName = NULL;
  1902.  
  1903.         if (m_pAIHandler->m_pPreviousBehavior.GetPtr())
  1904.         {
  1905.                 m_pAIHandler->m_pPreviousBehavior->GetValue("name", szName) || m_pAIHandler->m_pPreviousBehavior->GetValue("Name", szName);
  1906.         }
  1907.  
  1908.         return(szName);
  1909. }
  1910.  
  1911. //
  1912. //---------------------------------------------------------------------------------------------------------------
  1913. float CAIProxy::GetActorHealth() const
  1914. {
  1915.         const IActor* pActor = GetActor();
  1916.         if (pActor != NULL)
  1917.                 return pActor->GetHealth();
  1918.  
  1919.         const IVehicleSystem* pVehicleSystem = CCryAction::GetCryAction()->GetIVehicleSystem();
  1920.         const IVehicle* pVehicle = const_cast<IVehicleSystem*>(pVehicleSystem)->GetVehicle(m_pGameObject->GetEntityId());
  1921.         if (pVehicle)
  1922.                 return ((1.0f - pVehicle->GetDamageRatio()) * 1000.0f);
  1923.  
  1924.         return 0.0f;
  1925. }
  1926.  
  1927. //
  1928. //---------------------------------------------------------------------------------------------------------------
  1929. float CAIProxy::GetActorMaxHealth() const
  1930. {
  1931.         const IActor* pActor = GetActor();
  1932.         if (pActor != NULL)
  1933.                 return pActor->GetMaxHealth();
  1934.  
  1935.         const IVehicleSystem* pVehicleSystem = CCryAction::GetCryAction()->GetIVehicleSystem();
  1936.         const IVehicle* pVehicle = const_cast<IVehicleSystem*>(pVehicleSystem)->GetVehicle(m_pGameObject->GetEntityId());
  1937.         if (pVehicle)
  1938.                 return 1000.0f;
  1939.  
  1940.         return 1.0f;
  1941. }
  1942.  
  1943. //
  1944. //---------------------------------------------------------------------------------------------------------------
  1945. int CAIProxy::GetActorArmor() const
  1946. {
  1947.         const IActor* pActor = GetActor();
  1948.         if (pActor != NULL)
  1949.                 return pActor->GetArmor();
  1950.         return 0;
  1951. }
  1952.  
  1953. //
  1954. //---------------------------------------------------------------------------------------------------------------
  1955. int CAIProxy::GetActorMaxArmor() const
  1956. {
  1957.         const IActor* pActor = GetActor();
  1958.         if (pActor != NULL)
  1959.                 return pActor->GetMaxArmor();
  1960.         return 0;
  1961. }
  1962.  
  1963. //
  1964. //---------------------------------------------------------------------------------------------------------------
  1965. bool CAIProxy::GetActorIsFallen() const
  1966. {
  1967.         IActor* pActor = GetActor();
  1968.         if (pActor != NULL)
  1969.                 return pActor->IsFallen();
  1970.         return false;
  1971. }
  1972.  
  1973. //
  1974. //---------------------------------------------------------------------------------------------------------------
  1975. bool CAIProxy::IsDead() const
  1976. {
  1977.         if (const IActor* pActor = GetActor())
  1978.                 return pActor->IsDead();
  1979.  
  1980.         IVehicleSystem* pVehicleSystem = CCryAction::GetCryAction()->GetIVehicleSystem();
  1981.         IVehicle* pVehicle = pVehicleSystem->GetVehicle(m_pGameObject->GetEntityId());
  1982.         return pVehicle ? pVehicle->IsDestroyed() : false;
  1983. }
  1984.  
  1985. //
  1986. //----------------------------------------------------------------------------------------------------------
  1987. void CAIProxy::SetBehaviour(const char* szBehavior, const IAISignalExtraData* pData)
  1988. {
  1989.         if (m_pAIHandler)
  1990.         {
  1991.                 m_pAIHandler->SetBehavior(szBehavior, pData);
  1992.         }
  1993. }
  1994.  
  1995. //
  1996. //----------------------------------------------------------------------------------------------------------
  1997. float CAIProxy::LinearInterp(float x, float k, float A, float B, float C)
  1998. {
  1999.         // (MATT) Surely this is in CryCommon somewhere {2009/01/27}
  2000.         if (x < k)
  2001.         {
  2002.                 x = x / k;
  2003.                 return A + (B - A) * x;
  2004.         }
  2005.         else
  2006.         {
  2007.                 x = (x - k) / (1.0f - k);
  2008.                 return B + (C - B) * x;
  2009.         }
  2010. }
  2011.  
  2012. //
  2013. //----------------------------------------------------------------------------------------------------------
  2014. float CAIProxy::QuadraticInterp(float x, float k, float A, float B, float C)
  2015. {
  2016.         // (MATT) Surely this is in CryCommon somewhere {2009/01/27}
  2017.         float a = (A - B - A * k + C * k) / (k - k * k);
  2018.         float b = -(A - B - A * k * k + C * k * k) / (k - k * k);
  2019.         float c = A;
  2020.  
  2021.         if (x < 1.0f)
  2022.                 return a * x * x + b * x + c;
  2023.         else
  2024.                 return (2.0f * a + b) * x + c - a;
  2025. }
  2026.  
  2027. void CAIProxy::RemoveWeaponListener(IWeapon* pWeapon)
  2028. {
  2029.         if (pWeapon)
  2030.         {
  2031.                 pWeapon->RemoveEventListener(this);
  2032.                 m_weaponListenerId = 0;
  2033.         }
  2034. }
  2035.  
  2036. IWeapon* CAIProxy::GetWeaponFromId(EntityId entityId)
  2037. {
  2038.         IItem* pItem = CCryAction::GetCryAction()->GetIItemSystem()->GetItem(entityId);
  2039.  
  2040.         return pItem ? pItem->GetIWeapon() : NULL;
  2041. }
  2042.  
  2043. bool CAIProxy::IsInCloseMeleeRange(IAIObject* aiObject, IAIActor* aiActor) const
  2044. {
  2045.         if (IAIObject* target = aiActor->GetAttentionTarget())
  2046.         {
  2047.                 float targetDistSq = (target->GetPos() - aiObject->GetPos()).GetLengthSquared();
  2048.                 float shortMeleeThresholdSq = square(aiActor->GetParameters().m_fMeleeRangeShort);
  2049.  
  2050.                 if (targetDistSq <= shortMeleeThresholdSq)
  2051.                 {
  2052.                         return true;
  2053.                 }
  2054.         }
  2055.  
  2056.         return false;
  2057. }
  2058.  
  2059. namespace AISpeed // should move somewhere in Game code instead (and also be removed from SmartPathFollower)
  2060. {
  2061. // Adjust speed so it goes to zero when near a target
  2062. //
  2063. // Clamps speed to zero when within 20cm
  2064. // Tries not to overshoot the target, taking into account the frameTime
  2065. // ---------------------------------------------------------------------------
  2066. void AdjustSpeedWhenNearingTarget(const float speed, const float distToTarget, const float frameTime, float* const pAdjustedSpeed, bool* const pReachedEnd)
  2067. {
  2068.         const float MinDistanceToEnd = 0.2f;
  2069.         const float MaxTimeStep = 0.5f;
  2070.  
  2071.         // This is used to vaguely indicate if the FT has reached path end and so has the agent
  2072.         *pReachedEnd = distToTarget < max(MinDistanceToEnd, speed * min(frameTime, MaxTimeStep));
  2073.  
  2074.         float slowDownDist = 1.2f;
  2075.         // Scale speed down when within slowDownDist as a safety against instability
  2076.         // (magic numbers is to mimic the old behavior in the worst case; it reduced a speed
  2077.         // of about 7.5m/s, to 0.75m/s over the slowDownDist)
  2078.         *pAdjustedSpeed = *pReachedEnd ? 0.0f : min(speed, 0.75f + 7.0f * distToTarget / slowDownDist);
  2079. }
  2080. }
  2081.  
  2082. //
  2083. // ---------------------------------------------------------------------------
  2084.  
downloadAIProxy.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