BVB Source Codes

CRYENGINE Show Leader.cpp Source code

Return Download CRYENGINE: download Leader.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /********************************************************************
  4.    -------------------------------------------------------------------------
  5.    File name:   Leader.cpp
  6.  
  7.    Description: Class Implementation for CLeader
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    Created by Kirill Bulatsev
  12.    - 01:06:2005   : serialization support added
  13.  
  14.  *********************************************************************/
  15.  
  16. #include "StdAfx.h"
  17. #include "Leader.h"
  18. #include "LeaderAction.h"
  19. #include "CAISystem.h"
  20. #include <CrySystem/ISystem.h>
  21. #include "Puppet.h"
  22. #include "AIPlayer.h"
  23. #include <CryScriptSystem/IScriptSystem.h>
  24. #include <CryEntitySystem/IEntitySystem.h>
  25. #include <CryPhysics/IPhysics.h>
  26. #include <set>
  27. #include <limits>
  28. #include <CrySystem/IConsole.h>
  29. #include <CryNetwork/ISerialize.h>
  30.  
  31. //
  32. //----------------------------------------------------------------------------------------------------
  33. CLeader::CLeader(int iGroupID) :
  34.         m_pCurrentAction(NULL)
  35.         , m_vForcedPreferredPos(ZERO)
  36.         , m_bKeepEnabled(false)
  37.         , m_vMarkedPosition(0, 0, 0)
  38. {
  39.         _fastcast_CLeader = true;
  40.  
  41.         m_groupId = iGroupID;
  42.         SetName("TeamLeader");
  43.         SetAssociation(NILREF);
  44.         m_bLeaderAlive = true;
  45.         m_pGroup = GetAISystem()->GetAIGroup(iGroupID);
  46. }
  47.  
  48. //
  49. //----------------------------------------------------------------------------------------------------
  50. CLeader::~CLeader(void)
  51. {
  52.  
  53.         AbortExecution();
  54.         ReleaseFormation();
  55. }
  56.  
  57. //
  58. //----------------------------------------------------------------------------------------------------
  59. void CLeader::SetAssociation(CWeakRef<CAIObject> refAssociation)
  60. {
  61.         CCCPOINT(CLeader_SetAssociation);
  62.  
  63.         CAIObject::SetAssociation(refAssociation);
  64.         CAIObject* pObject = refAssociation.GetAIObject();
  65.         if (pObject && pObject->IsEnabled())
  66.                 m_bLeaderAlive = true;
  67. }
  68.  
  69. //
  70. //----------------------------------------------------------------------------------------------------
  71. void CLeader::Reset(EObjectResetType type)
  72. {
  73.  
  74.         CAIObject::Reset(type);
  75.         AbortExecution();
  76.         ReleaseFormation();
  77.         m_szFormationDescriptor.clear();
  78.         m_refEnemyTarget.Reset();
  79.         m_vForcedPreferredPos.Set(0, 0, 0);
  80.         m_bLeaderAlive = true;
  81.         m_State.ClearSignals();
  82. }
  83.  
  84. //
  85. //----------------------------------------------------------------------------------------------------
  86. bool CLeader::IsPlayer() const
  87. {
  88.         CAIObject* pObject = GetAssociation().GetAIObject();
  89.         if (pObject)
  90.                 return pObject->GetType() == AIOBJECT_PLAYER;
  91.         return false;
  92. }
  93.  
  94. //
  95. //----------------------------------------------------------------------------------------------------
  96. Vec3 CLeader::GetPreferedPos() const
  97. {
  98.         if (!m_vForcedPreferredPos.IsZero())
  99.                 return m_vForcedPreferredPos;
  100.  
  101.         CCCPOINT(CLeader_GetPreferedPos);
  102.  
  103.         CAIObject* pLeaderObject = GetAssociation().GetAIObject();
  104.         if (!pLeaderObject)
  105.                 return m_pGroup->GetAveragePosition();
  106.         else if (pLeaderObject->GetType() == AIOBJECT_PLAYER)
  107.         {
  108.                 return m_pGroup->GetAveragePosition();
  109.         }
  110.         else
  111.                 return pLeaderObject->GetPos();
  112. }
  113.  
  114. //
  115. //----------------------------------------------------------------------------------------------------
  116. void CLeader::Update(EObjectUpdate type)
  117. {
  118.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  119.  
  120.         if (!GetAssociation().ValidateOrReset() && !m_bKeepEnabled)
  121.                 return;
  122.  
  123.         UpdateEnemyStats();
  124.  
  125.         while (!m_State.vSignals.empty())
  126.         {
  127.                 AISIGNAL sstruct = m_State.vSignals.back();
  128.                 m_State.vSignals.pop_back();
  129.                 ProcessSignal(sstruct);
  130.         }
  131.  
  132.         for (TUnitList::iterator unitItr = m_pGroup->GetUnits().begin(); unitItr != m_pGroup->GetUnits().end(); ++unitItr)
  133.         {
  134.                 CCCPOINT(CLeader_Update);
  135.  
  136.                 CUnitImg& curUnit = (*unitItr);
  137.                 if (!curUnit.IsPlanFinished())
  138.                 {
  139.                         if (curUnit.Idle() && !curUnit.IsBlocked())
  140.                                 curUnit.ExecuteTask();
  141.                 }
  142.         }
  143.  
  144.         CLeaderAction::eActionUpdateResult eUpdateResult;
  145.         if (m_pCurrentAction && (eUpdateResult = m_pCurrentAction->Update()) != CLeaderAction::ACTION_RUNNING)
  146.         {
  147.                 // order completed or not issued
  148.                 bool search = m_pCurrentAction->GetType() == LA_ATTACK && !IsPlayer() && !m_pGroup->GetAttentionTarget(true, true).IsValid();
  149.                 ELeaderAction iActionType = m_pCurrentAction->GetType();
  150.                 ELeaderActionSubType iActionSubType = m_pCurrentAction->GetSubType();
  151.                 // get previous leaderAction's unit properties
  152.                 uint32 unitProperties = m_pCurrentAction->GetUnitProperties();
  153.                 AbortExecution();
  154.                 // inform the puppet that the order is done
  155.                 CWeakRef<CAIObject> refTarget = m_pGroup->GetAttentionTarget(true);
  156.                 CAIObject* pTarget = refTarget.GetAIObject();
  157.                 AISignalExtraData* pData = new AISignalExtraData;
  158.                 pData->iValue = iActionType;
  159.                 pData->iValue2 = iActionSubType;
  160.                 if (pTarget)
  161.                 {
  162.                         // target id
  163.                         IEntity* pTargetEntity = NULL;
  164.                         if (CPuppet* pPuppet = pTarget->CastToCPuppet())
  165.                                 pTargetEntity = pPuppet->GetEntity();
  166.                         else if (CAIPlayer* pPlayer = pTarget->CastToCAIPlayer())
  167.                                 pTargetEntity = pPlayer->GetEntity();
  168.                         //target name
  169.                         if (pTargetEntity)
  170.                                 pData->nID = pTargetEntity->GetId();
  171.                         pData->SetObjectName(pTarget->GetName());
  172.                         //target distance
  173.                         Vec3 avgPos = m_pGroup->GetAveragePosition(IAIGroup::AVMODE_PROPERTIES, unitProperties);
  174.                         pData->fValue = (avgPos - m_pGroup->GetEnemyAveragePosition()).GetLength();
  175.                         pData->point = m_pGroup->GetEnemyAveragePosition();
  176.  
  177.                         CCCPOINT(CLeader_Update_A);
  178.                 }
  179.  
  180.                 int sigFilter;
  181.                 CAIActor* pDestActor = CastToCAIActorSafe(GetAssociation().GetAIObject());
  182.                 if (pDestActor && pDestActor->IsEnabled())
  183.                         sigFilter = SIGNALFILTER_SENDER;
  184.                 else
  185.                 {
  186.                         sigFilter = SIGNALFILTER_SUPERGROUP;
  187.                         if (!m_pGroup->GetUnits().empty())
  188.                         {
  189.                                 TUnitList::iterator itUnit = m_pGroup->GetUnits().begin();
  190.                                 pDestActor = itUnit->m_refUnit.GetAIObject();
  191.                         }
  192.                 }
  193.  
  194.                 if (pDestActor)
  195.                 {
  196.                         if (eUpdateResult == CLeaderAction::ACTION_DONE)
  197.                                 GetAISystem()->SendSignal(sigFilter, 10, "OnLeaderActionCompleted", pDestActor, pData);
  198.                         else
  199.                                 GetAISystem()->SendSignal(sigFilter, 10, "OnLeaderActionFailed", pDestActor, pData);
  200.                 }
  201.  
  202.         }
  203.  
  204. }
  205.  
  206. //
  207. //----------------------------------------------------------------------------------------------------
  208. void CLeader::ProcessSignal(AISIGNAL& signal)
  209. {
  210.         if (m_pCurrentAction && m_pCurrentAction->ProcessSignal(signal))
  211.                 return;
  212.  
  213.         CCCPOINT(CLeader_ProcessSignal);
  214.  
  215.         AISignalExtraData data;
  216.         if (signal.pEData)
  217.         {
  218.                 data = *(AISignalExtraData*)signal.pEData;
  219.                 delete (AISignalExtraData*)signal.pEData;
  220.                 signal.pEData = NULL;
  221.         }
  222.  
  223.         if (signal.Compare(gAIEnv.SignalCRCs.m_nAIORD_ATTACK))
  224.         {
  225.                 ELeaderActionSubType attackType = static_cast<ELeaderActionSubType>(data.iValue);
  226.                 LeaderActionParams params;
  227.                 params.type = LA_ATTACK;
  228.                 params.subType = attackType;
  229.                 params.unitProperties = data.iValue2;
  230.                 params.id = data.nID;
  231.                 params.pAIObject = gAIEnv.pAIObjectManager->GetAIObjectByName(data.GetObjectName());
  232.                 params.fDuration = data.fValue;
  233.                 params.vPoint = data.point;
  234.                 params.name = data.GetObjectName();
  235.                 Attack(&params);
  236.         }
  237.         else if (signal.Compare(gAIEnv.SignalCRCs.m_nAIORD_SEARCH))
  238.         {
  239.                 Vec3 startPoint = data.point;
  240.                 Search((startPoint.IsZero() ? m_pGroup->GetEnemyPositionKnown() : startPoint), data.fValue, (data.iValue ? data.iValue : UPR_ALL), data.iValue2);
  241.         }
  242.         else if (signal.Compare(gAIEnv.SignalCRCs.m_nOnScaleFormation))
  243.         {
  244.                 CCCPOINT(CLeader_ProcessSignal_ScaleFormation);
  245.  
  246.                 float fScale = data.fValue;
  247.                 CAIObject* pFormationOwner = m_refFormationOwner.GetAIObject();
  248.                 if (pFormationOwner)
  249.                         pFormationOwner->m_pFormation->SetScale(fScale);
  250.         }
  251.         else if (signal.Compare(gAIEnv.SignalCRCs.m_nRPT_LeaderDead))
  252.         {
  253.                 if (!m_pCurrentAction) // if there is a current action, the OnLeaderDied signal will be sent after the action finishes
  254.                 {
  255.                         CAIObject* pAILeader = GetAssociation().GetAIObject();
  256.                         if (pAILeader && m_bLeaderAlive)
  257.                         {
  258.                                 GetAISystem()->SendSignal(SIGNALFILTER_SUPERGROUP, 0, "OnLeaderDied", pAILeader);
  259.                                 m_bLeaderAlive = false;
  260.                         }
  261.                 }
  262.         }
  263.         else if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity(signal.senderID))
  264.         {
  265.                 if (signal.Compare(gAIEnv.SignalCRCs.m_nOnUnitDied))
  266.                 {
  267.                         CAIActor* pActor = CastToCAIActorSafe(pEntity->GetAI());
  268.                         if (m_pCurrentAction)
  269.                                 m_pCurrentAction->DeadUnitNotify(pActor);
  270.  
  271.                         TUnitList::iterator senderUnit = std::find(m_pGroup->GetUnits().begin(), m_pGroup->GetUnits().end(), pActor);
  272.                         if (senderUnit != m_pGroup->GetUnits().end())
  273.                                 m_pGroup->RemoveMember(pActor);
  274.                         // TO DO: remove use action from list if it's owned by this unit
  275.                 }
  276.                 else if (signal.Compare(gAIEnv.SignalCRCs.m_nOnUnitBusy))
  277.                 {
  278.                         CAIActor* pActor = CastToCAIActorSafe(pEntity->GetAI());
  279.                         TUnitList::iterator senderUnit = std::find(m_pGroup->GetUnits().begin(), m_pGroup->GetUnits().end(), pActor);
  280.  
  281.                         if (senderUnit != m_pGroup->GetUnits().end())
  282.                         {
  283.                                 if (m_pCurrentAction)
  284.                                         m_pCurrentAction->BusyUnitNotify(*senderUnit);
  285.  
  286.                                 // TODO: busy units will be removed by now...
  287.                                 // Now it isn't so bad because they will stay busy forever.
  288.                                 // However, it's only a temporary solution!
  289.                                 // They should still be there but marked as busy.
  290.                                 m_pGroup->RemoveMember(pActor);
  291.                         }
  292.                 }
  293.                 else if (signal.Compare(gAIEnv.SignalCRCs.m_nOnUnitSuspended))
  294.                 {
  295.                         CAIActor* pActor = CastToCAIActorSafe(pEntity->GetAI());
  296.                         TUnitList::iterator senderUnit = std::find(m_pGroup->GetUnits().begin(), m_pGroup->GetUnits().end(), pActor);
  297.  
  298.                         if (senderUnit != m_pGroup->GetUnits().end())
  299.                         {
  300.                                 if (m_pCurrentAction)
  301.                                         m_pCurrentAction->BusyUnitNotify(*senderUnit);
  302.                         }
  303.                 }
  304.                 else if (signal.Compare(gAIEnv.SignalCRCs.m_nOnUnitResumed))
  305.                 {
  306.                         CAIActor* pActor = CastToCAIActorSafe(pEntity->GetAI());
  307.                         TUnitList::iterator senderUnit = std::find(m_pGroup->GetUnits().begin(), m_pGroup->GetUnits().end(), pActor);
  308.  
  309.                         if (senderUnit != m_pGroup->GetUnits().end())
  310.                         {
  311.                                 if (m_pCurrentAction)
  312.                                         m_pCurrentAction->ResumeUnit(*senderUnit);
  313.                         }
  314.                 }
  315.                 else if (signal.Compare(gAIEnv.SignalCRCs.m_nOnSetUnitProperties))
  316.                 {
  317.                         CAIActor* pActor = CastToCAIActorSafe(pEntity->GetAI());
  318.                         TUnitList::iterator senderUnit = std::find(m_pGroup->GetUnits().begin(), m_pGroup->GetUnits().end(), pActor);
  319.  
  320.                         if (senderUnit != m_pGroup->GetUnits().end())
  321.                                 senderUnit->SetProperties(data.iValue);
  322.                 }
  323.         }
  324.  
  325.         if (m_pCurrentAction)
  326.         {
  327.                 if (signal.Compare(gAIEnv.SignalCRCs.m_nAIORD_REPORTDONE))
  328.                 {
  329.                         if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity(signal.senderID))
  330.                         {
  331.                                 CAIActor* pActor = CastToCAIActorSafe(pEntity->GetAI());
  332.                                 TUnitList::iterator senderUnit = std::find(m_pGroup->GetUnits().begin(), m_pGroup->GetUnits().end(), pActor);
  333.                                 if (senderUnit != m_pGroup->GetUnits().end())
  334.                                 {
  335.                                         (*senderUnit).TaskExecuted();
  336.                                         (*senderUnit).ExecuteTask();
  337.                                 }
  338.                         }
  339.                 }
  340.                 else if (signal.Compare(gAIEnv.SignalCRCs.m_nOnAbortAction))
  341.                 {
  342.                         AbortExecution();
  343.                         CLeader* pAILeader = CastToCLeaderSafe(GetAssociation().GetAIObject());
  344.                         if (pAILeader)
  345.                                 pAILeader->SetSignal(1, "OnAbortAction", 0, 0, gAIEnv.SignalCRCs.m_nOnAbortAction);
  346.                 }
  347.                 else if (signal.Compare(gAIEnv.SignalCRCs.m_nOnFormationPointReached)) /*if(!strcmp(signal.strText, "OnFormationPointReached"))*/
  348.                 {
  349.                         /*
  350.                            // TO DO: what to do with this?
  351.                            IEntity* pEntity = (IEntity*)signal.pSender;
  352.                            assert(pEntity);
  353.                            CAIObject* pAIObj = (CAIObject*)pEntity->GetAI();
  354.                            assert(pAIObj);
  355.                            TUnitList::iterator itEnd =  m_pGroup->GetUnits().end();
  356.                          */
  357.                 }
  358.         }
  359.         else if (signal.Compare(gAIEnv.SignalCRCs.m_nOnKeepEnabled))
  360.                 m_bKeepEnabled = true;
  361. }
  362.  
  363. //
  364. //----------------------------------------------------------------------------------------------------
  365. void CLeader::AbortExecution(int priority)
  366. {
  367.  
  368.         ClearAllPlannings(UPR_ALL, priority);
  369.  
  370.         if (m_pCurrentAction)
  371.         {
  372.                 CCCPOINT(CLeader_AbortExecution);
  373.  
  374.                 delete m_pCurrentAction;
  375.                 m_pCurrentAction = NULL;
  376.         }
  377. }
  378.  
  379. //
  380. //----------------------------------------------------------------------------------------------------
  381. void CLeader::ClearAllPlannings(uint32 unitProp, int priority)
  382. {
  383.         for (TUnitList::iterator unitItr = m_pGroup->GetUnits().begin(); unitItr != m_pGroup->GetUnits().end(); ++unitItr)
  384.         {
  385.                 CUnitImg& unit = *unitItr;
  386.                 CAIObject* pUnit = unit.m_refUnit.GetAIObject();
  387.                 if (pUnit->IsEnabled() && (unit.GetProperties() & unitProp))
  388.                 {
  389.                         CUnitImg& curUnit = (*unitItr);
  390.                         curUnit.ClearPlanning(priority);
  391.  
  392.                         CCCPOINT(CLeader_ClearAllPlannings);
  393.                 }
  394.         }
  395. }
  396.  
  397. //
  398. //----------------------------------------------------------------------------------------------------
  399. bool CLeader::IsIdle() const
  400. {
  401.         for (TUnitList::const_iterator itUnit = m_pGroup->GetUnits().begin(); itUnit != m_pGroup->GetUnits().end(); ++itUnit)
  402.                 if (!itUnit->Idle() && itUnit->m_refUnit.GetAIObject()->IsEnabled())
  403.                         return false;
  404.         return true;
  405. }
  406.  
  407. //
  408. //----------------------------------------------------------------------------------------------------
  409. void CLeader::Attack(const LeaderActionParams* pParams)
  410. {
  411.  
  412.         AbortExecution(PRIORITY_NORMAL);
  413.         LeaderActionParams defaultParams(LA_ATTACK, LAS_DEFAULT);
  414.         m_pCurrentAction = CreateAction(pParams ? pParams : &defaultParams);
  415.         m_pCurrentAction->SetPriority(PRIORITY_NORMAL);
  416. }
  417.  
  418. //
  419. //----------------------------------------------------------------------------------------------------
  420. void CLeader::Search(const Vec3& targetPos, float searchDistance, uint32 unitProperties, int searchAIObjectType)
  421. {
  422.         if (m_pCurrentAction && m_pCurrentAction->GetType() == LA_SEARCH)
  423.                 return;
  424.         AbortExecution(PRIORITY_NORMAL);
  425.         LeaderActionParams params(LA_SEARCH, LAS_DEFAULT);
  426.         params.unitProperties = unitProperties;
  427.         params.fSize = searchDistance;
  428.         params.vPoint = targetPos;
  429.         params.iValue = searchAIObjectType;
  430.         m_pCurrentAction = CreateAction(&params);
  431.         m_pCurrentAction->SetPriority(PRIORITY_NORMAL);
  432. }
  433.  
  434. void CLeader::OnEnemyStatsUpdated(const Vec3& avgEnemyPos, const Vec3& oldAvgEnemyPos)
  435. {
  436.         if (!IsPlayer())
  437.         {
  438.                 if (avgEnemyPos.IsZero() && !oldAvgEnemyPos.IsZero())
  439.                 {
  440.                         CLeader* pAILeader = CastToCLeaderSafe(GetAssociation().GetAIObject());
  441.                         if (pAILeader)
  442.                                 pAILeader->SetSignal(1, "OnNoGroupTarget", 0, 0, gAIEnv.SignalCRCs.m_nOnNoGroupTarget);
  443.                 }
  444.                 else if (!avgEnemyPos.IsZero() && oldAvgEnemyPos.IsZero())
  445.                 {
  446.                         CAIObject* pAILeader = GetAssociation().GetAIObject();
  447.                         CWeakRef<CAIObject> refTarget = m_pGroup->GetAttentionTarget(true, true);
  448.                         CAIObject* pTarget = refTarget.GetAIObject();
  449.  
  450.                         if (pTarget && pAILeader)
  451.                         {
  452.                                 IEntity* pEntity = pTarget->GetEntity();
  453.                                 if (pEntity)
  454.                                 {
  455.                                         AISignalExtraData* pData = new AISignalExtraData;
  456.                                         pData->nID = pEntity->GetId();
  457.                                         GetAISystem()->SendSignal(SIGNALFILTER_SENDER, 0, "OnGroupTarget", pAILeader, pData);
  458.                                 }
  459.                         }
  460.                 }
  461.         }
  462. }
  463.  
  464. //
  465. //-------------------------------------------------------------------------------------------
  466. void CLeader::UpdateEnemyStats()
  467. {
  468.         // update beacon
  469.         if (m_pCurrentAction)
  470.                 m_pCurrentAction->UpdateBeacon();
  471.         else
  472.         {
  473.                 CWeakRef<CAIObject> refBeaconUser = GetAssociation();
  474.                 if (!refBeaconUser.IsValid() || IsPlayer())
  475.                         for (TUnitList::const_iterator it = m_pGroup->GetUnits().begin(); it != m_pGroup->GetUnits().end(); ++it)
  476.                         {
  477.                                 CAIObject* pUnit = it->m_refUnit.GetAIObject();
  478.                                 if (pUnit && it->m_refUnit != refBeaconUser && pUnit->IsEnabled())
  479.                                 {
  480.                                         refBeaconUser = it->m_refUnit;
  481.                                         break;
  482.                                 }
  483.                         }
  484.  
  485.                 if (refBeaconUser.IsNil())
  486.                         return;
  487.  
  488.                 const Vec3& avgEnemyPos(m_pGroup->GetEnemyAveragePosition());
  489.                 const Vec3& avgLiveEnemyPos(m_pGroup->GetLiveEnemyAveragePosition());
  490.  
  491.                 if (!avgLiveEnemyPos.IsZero())
  492.                         GetAISystem()->UpdateBeacon(GetGroupId(), avgLiveEnemyPos, refBeaconUser.GetAIObject());
  493.                 else if (!avgEnemyPos.IsZero())
  494.                         GetAISystem()->UpdateBeacon(GetGroupId(), avgEnemyPos, refBeaconUser.GetAIObject());
  495.                 Vec3 vEnemyDir = m_pGroup->GetEnemyAverageDirection(true, false);
  496.                 if (!vEnemyDir.IsZero())
  497.                 {
  498.                         IAIObject* pBeacon = GetAISystem()->GetBeacon(GetGroupId());
  499.                         if (pBeacon)
  500.                         {
  501.                                 pBeacon->SetEntityDir(vEnemyDir);
  502.                                 pBeacon->SetMoveDir(vEnemyDir);
  503.                         }
  504.                 }
  505.  
  506.                 CCCPOINT(CLeader_UpdateEnemyStats);
  507.         }
  508. }
  509.  
  510. //
  511. //--------------------------------------------------------------------------------------------
  512. void CLeader::OnObjectRemoved(CAIObject* pObject)
  513. {
  514.         CAIActor::OnObjectRemoved(pObject);
  515. }
  516.  
  517. //---------------------------------------------------------------------------------------
  518.  
  519. Vec3 CLeader::GetHidePoint(const CAIObject* pAIObject, const CObstacleRef& obstacle) const
  520. {
  521.         if (obstacle.GetAnchor() || obstacle.GetNodeIndex())
  522.                 return obstacle.GetPos();
  523.  
  524.         if (obstacle.GetVertex() < 0)
  525.                 return Vec3(0.0f, 0.0f, 0.0f);
  526.  
  527.         // lets create the place where we will hide
  528.  
  529.         Vec3 vHidePos = obstacle.GetPos();
  530.         const CAIActor* pActor = pAIObject->CastToCAIActor();
  531.         float fDistanceToEdge = pActor->GetParameters().m_fPassRadius + obstacle.GetApproxRadius() + 1.f;
  532.         Vec3 enemyPosition = m_pGroup->GetEnemyPosition(pAIObject);
  533.  
  534.         Vec3 vHideDir = vHidePos - enemyPosition;
  535.         vHideDir.z = 0.f;
  536.         vHideDir.NormalizeSafe();
  537.  
  538.         ray_hit hit;
  539.         while (1)
  540.         {
  541.                 int rayresult(0);
  542.                 rayresult = gAIEnv.pWorld->RayWorldIntersection(
  543.                   vHidePos - vHideDir * 0.5f, vHideDir * 5.f, COVER_OBJECT_TYPES,
  544.                   AI_VISION_RAY_CAST_FLAG_BLOCKED_BY_SOLID_COVER | AI_VISION_RAY_CAST_FLAG_BLOCKED_BY_SOFT_COVER,
  545.                   &hit, 1);
  546.  
  547.                 if (rayresult)
  548.                 {
  549.                         if (hit.n.Dot(vHideDir) < 0)
  550.                                 vHidePos += vHideDir * fDistanceToEdge;
  551.                         else
  552.                         {
  553.                                 vHidePos = hit.pt + vHideDir * 2.0f;
  554.                                 break;
  555.                         }
  556.                 }
  557.                 else
  558.                 {
  559.                         vHidePos += vHideDir * 3.0f;
  560.                         break;
  561.                 }
  562.         }
  563.  
  564.         return vHidePos;
  565. }
  566.  
  567. bool CLeader::LeaderCreateFormation(const char* szFormationDescr, const Vec3& vTargetPos, bool bIncludeLeader, uint32 unitProp, CAIObject* pOwner)
  568. {
  569.         // (MATT) Note that this code seems to imply that pOwner must be an Actor - can the argument change? {2009/02/13}
  570.  
  571.         ReleaseFormation();
  572.         int unitCount = m_pGroup->GetUnitCount(unitProp);
  573.         if (unitCount == 0)
  574.                 return false;
  575.  
  576.         // Select formation owner
  577.         CWeakRef<CAIObject> refAILeader = GetAssociation();
  578.  
  579.         CAIActor* pLeaderActor = CastToCAIActorSafe(refAILeader.GetAIObject());
  580.  
  581.         TUnitList::iterator itLeader = m_pGroup->GetUnit(pLeaderActor);
  582.  
  583.         if (IsPlayer())
  584.                 m_refFormationOwner = refAILeader;
  585.         else if (pOwner)
  586.                 m_refFormationOwner = GetWeakRef(pOwner);
  587.         else if (vTargetPos.IsZero() && bIncludeLeader && itLeader != m_pGroup->GetUnits().end() && (itLeader->GetProperties() & unitProp))
  588.         {
  589.                 m_refFormationOwner = GetAssociation();  // get Leader puppet by default
  590.                 if (!m_refFormationOwner.IsValid())
  591.                         m_refFormationOwner = m_pGroup->GetUnits().begin()->m_refUnit;
  592.         }
  593.         else
  594.         {
  595.                 float fMinDist = std::numeric_limits<float>::max();
  596.                 for (TUnitList::iterator itUnit = m_pGroup->GetUnits().begin(); itUnit != m_pGroup->GetUnits().end(); ++itUnit)
  597.                 {
  598.                         if (!bIncludeLeader && itUnit->m_refUnit == refAILeader)
  599.                                 continue;
  600.                         if (!(itUnit->GetProperties() & unitProp))
  601.                                 continue;
  602.                         CAIObject* pUnit = itUnit->m_refUnit.GetAIObject();
  603.                         if (!pUnit)
  604.                                 continue;
  605.                         float fDist = (pUnit->GetPos() - vTargetPos).GetLengthSquared();
  606.                         if (fDist < fMinDist)
  607.                         {
  608.                                 m_refFormationOwner = itUnit->m_refUnit;
  609.                                 fMinDist = fDist;
  610.                         }
  611.                 }
  612.         }
  613.         if (!m_refFormationOwner.IsValid())
  614.                 return false;
  615.  
  616.         CCCPOINT(CLeader_LeaderCreateFormation);
  617.  
  618.         CAIObject* const pFormationOwner = m_refFormationOwner.GetAIObject();
  619.         if (pFormationOwner->CreateFormation(szFormationDescr, vTargetPos))
  620.         {
  621.                 m_szFormationDescriptor = szFormationDescr;
  622.         }
  623.  
  624.         if (pFormationOwner->m_pFormation)
  625.         {
  626.                 //assign places to team members
  627.                 pFormationOwner->m_pFormation->GetNewFormationPoint(StaticCast<CAIActor>(m_refFormationOwner), 0);
  628.  
  629.                 AssignFormationPoints(bIncludeLeader, unitProp);
  630.  
  631.                 m_refPrevFormationOwner = m_refFormationOwner;
  632.                 return true;
  633.         }
  634.         m_refFormationOwner.Reset();
  635.         return false;
  636. }
  637.  
  638. bool CLeader::ReleaseFormation()
  639. {
  640.         CAIObject* pFormationOwner = m_refFormationOwner.GetAIObject();
  641.         if (pFormationOwner && pFormationOwner->m_pFormation)
  642.         {
  643.                 CAIActor* pOwnerActor = pFormationOwner->CastToCAIActor();
  644.                 int iOwnerGroup = GetGroupId();
  645.                 if (pOwnerActor)
  646.                         iOwnerGroup = pOwnerActor->GetGroupId();
  647.                 else if (pFormationOwner->GetSubType() == IAIObject::STP_BEACON)
  648.                         iOwnerGroup = GetAISystem()->GetBeaconGroupId(pFormationOwner);
  649.  
  650.                 for (TUnitList::iterator itUnit = m_pGroup->GetUnits().begin(); itUnit != m_pGroup->GetUnits().end(); ++itUnit)
  651.                         FreeFormationPoint(itUnit->m_refUnit);
  652.         }
  653.  
  654.         // force all unit to release their possible formations
  655.         for (TUnitList::iterator itUnit = m_pGroup->GetUnits().begin(); itUnit != m_pGroup->GetUnits().end(); ++itUnit)
  656.         {
  657.                 itUnit->m_FormationPointIndex = -1;
  658.         }
  659.  
  660.         bool ret = false;
  661.         if (pFormationOwner && pFormationOwner->m_pFormation)
  662.                 ret = pFormationOwner->ReleaseFormation();
  663.         m_refFormationOwner.Reset();
  664.  
  665.         return ret;
  666. }
  667.  
  668. CWeakRef<CAIObject> CLeader::GetNewFormationPoint(CWeakRef<CAIObject> refRequester, int iPointType)
  669. {
  670.         // (MATT) Code strongly implied requester must be an actor (GetClosestPoint) {2009/02/14}
  671.         CAIObject* pFormationOwner = m_refFormationOwner.GetAIObject();
  672.         CAIObject* pFormationPoint = NULL;
  673.         CAIActor* const pRequester = static_cast<CAIActor*>(refRequester.GetAIObject());
  674.         if (pFormationOwner && pFormationOwner->m_pFormation)
  675.         {
  676.                 if (iPointType <= 0)
  677.                 {
  678.                         int iFPIndex = GetFormationPointIndex(pRequester);
  679.                         if (iFPIndex >= 0)
  680.                                 pFormationPoint = pFormationOwner->m_pFormation->GetNewFormationPoint(StaticCast<CAIActor>(refRequester), iFPIndex);
  681.                 }
  682.                 else
  683.                         pFormationPoint = pFormationOwner->m_pFormation->GetClosestPoint(pRequester, true, iPointType);
  684.         }
  685.         return GetWeakRef(pFormationPoint);
  686. }
  687.  
  688. int CLeader::GetFormationPointIndex(const CAIObject* pAIObject)  const
  689. {
  690.         if (pAIObject->GetType() == AIOBJECT_PLAYER)
  691.                 return 0;
  692.         const CAIActor* pActor = pAIObject->CastToCAIActor();
  693.         TUnitList::const_iterator itUnit = std::find(m_pGroup->GetUnits().begin(), m_pGroup->GetUnits().end(), pActor);
  694.  
  695.         if (itUnit != m_pGroup->GetUnits().end())
  696.                 return (*itUnit).m_FormationPointIndex;
  697.  
  698.         return -1;
  699. }
  700.  
  701. //-----------------------------------------------------------------------------------------------------------
  702. CWeakRef<CAIObject> CLeader::GetFormationPointSight(const CPipeUser* pRequester) const
  703. {
  704.         CAIObject* const pFormationOwner = m_refFormationOwner.GetAIObject();
  705.         if (pFormationOwner)
  706.         {
  707.                 CFormation* pFormation = pFormationOwner->m_pFormation;
  708.                 if (pFormation)
  709.                         return GetWeakRef(pFormation->GetFormationDummyTarget(GetWeakRef(pRequester)));
  710.         }
  711.         return NILREF;
  712. }
  713.  
  714. //-----------------------------------------------------------------------------------------------------------
  715. CWeakRef<CAIObject> CLeader::GetFormationPoint(CWeakRef<CAIObject> refRequester) const
  716. {
  717.         CAIObject* const pFormationOwner = m_refFormationOwner.GetAIObject();
  718.         if (pFormationOwner)
  719.         {
  720.                 CFormation* pFormation = pFormationOwner->m_pFormation;
  721.                 if (pFormation)
  722.                         return GetWeakRef(pFormation->GetFormationPoint(refRequester));
  723.         }
  724.         return NILREF;
  725. }
  726.  
  727. //-----------------------------------------------------------------------------------------------------------
  728. void CLeader::FreeFormationPoint(CWeakRef<CAIObject> refRequester) const
  729. {
  730.         CAIObject* const pFormationOwner = m_refFormationOwner.GetAIObject();
  731.         if (pFormationOwner && pFormationOwner->m_pFormation)
  732.                 pFormationOwner->m_pFormation->FreeFormationPoint(refRequester);
  733.  
  734. }
  735.  
  736. //-----------------------------------------------------------------------------------------------------------
  737. int CLeader::AssignFormationPoints(bool bIncludeLeader, uint32 unitProp)
  738. {
  739.         std::vector<bool> vPointTaken;
  740.         TClassUnitMap mapClassUnits;
  741.  
  742.         CAIObject* const pFormationOwner = m_refFormationOwner.GetAIObject();
  743.         if (!pFormationOwner)
  744.                 return 0;
  745.  
  746.         CFormation* pFormation = pFormationOwner->m_pFormation;
  747.         if (!pFormation)
  748.                 return 0;
  749.  
  750.         CCCPOINT(CLeader_AssignFormationPoints);
  751.  
  752.         TUnitList::iterator itUnitEnd = m_pGroup->GetUnits().end();
  753.         for (TUnitList::iterator it = m_pGroup->GetUnits().begin(); it != itUnitEnd; ++it)
  754.                 if (it->m_refUnit == m_refFormationOwner)
  755.                         it->m_FormationPointIndex = 0;
  756.                 else
  757.                         it->m_FormationPointIndex = -1;
  758.  
  759.         int iFreePoints = pFormation->CountFreePoints();
  760.         int iFormationSize = pFormation->GetSize();
  761.         int iTeamSize = m_pGroup->GetUnitCount(unitProp); //m_pGroup->GetUnits().size();
  762.         if (!m_pGroup->IsMember(pFormationOwner))
  763.                 iTeamSize++;
  764.         if (iTeamSize > iFreePoints)
  765.                 iTeamSize = iFreePoints;
  766.  
  767.         int building;
  768.         CAIActor* pOwnerActor = pFormationOwner->CastToCAIActor();
  769.         IAISystem::tNavCapMask navMask = (IsPlayer() || !pOwnerActor ? IAISystem::NAVMASK_ALL : pOwnerActor->GetMovementAbility().pathfindingProperties.navCapMask);
  770.  
  771.         bool bOwnerInTriangularRegion = (gAIEnv.pNavigation->CheckNavigationType(pFormationOwner->GetPos(), building, navMask) == IAISystem::NAV_TRIANGULAR);
  772.         TUnitList::iterator itUnit = m_pGroup->GetUnits().begin();
  773.  
  774.         std::vector<TUnitList::iterator> AssignedUnit;
  775.  
  776.         //assigned point 0 to owner
  777.         TUnitList::iterator itOwner = std::find(m_pGroup->GetUnits().begin(), m_pGroup->GetUnits().end(), pOwnerActor);
  778.         AssignedUnit.push_back(itOwner); // could be itUnitEnd if the owner is not in the units (i.e.player, beacon)
  779.  
  780.         for (int i = 1; i < iFormationSize; i++)
  781.                 AssignedUnit.push_back(itUnitEnd);
  782.  
  783.         CWeakRef<CAIObject> refAILeader = GetAssociation();
  784.         int iAssignedCount = 0;
  785.  
  786.         for (int k = 0; k < 3; k++) // this index determines the type of test
  787.         {
  788.                 for (int i = 1; i < iFormationSize; i++)
  789.                 {
  790.                         //formation points are sorted by distance to point 0
  791.                         //try to assign closest points to owner first, depending on their class
  792.                         CAIObject* pPoint = pFormation->GetFormationPoint(i);
  793.                         float fMinDist = 987654321.f;
  794.                         int index = -1;
  795.                         TUnitList::iterator itSelected = itUnitEnd;
  796.  
  797.                         for (itUnit = m_pGroup->GetUnits().begin(); itUnit != itUnitEnd; ++itUnit)
  798.                         {
  799.                                 CUnitImg& unit = (*itUnit);
  800.                                 if ((unit.GetProperties() & unitProp) && unit.m_refUnit != m_refFormationOwner
  801.                                     && unit.m_FormationPointIndex < 0 &&
  802.                                     (k == 0 && (unit.GetClass() == pFormation->GetPointClass(i)) || ///first give priority to points that have ONLY the requestor's class
  803.                                      k == 1 && AssignedUnit[i] == itUnitEnd && (unit.GetClass() & pFormation->GetPointClass(i)) ||// then consider points that have ALSO the requestor's class
  804.                                      k == 2 && AssignedUnit[i] == itUnitEnd && pFormation->GetPointClass(i) != SPECIAL_FORMATION_POINT)) // finally don't consider the class, excluding SPECIAL_FORMATION_POINT anyway
  805.                                 {
  806.                                         if (unit.m_refUnit == refAILeader && !bIncludeLeader)
  807.                                                 continue;
  808.                                         Vec3 endPos(pPoint->GetPos());
  809.                                         Vec3 otherPos(unit.m_refUnit.GetAIObject()->GetPos());
  810.                                         if (bOwnerInTriangularRegion)
  811.                                                 endPos.z = gEnv->p3DEngine->GetTerrainElevation(endPos.x, endPos.y);
  812.  
  813.                                         float fDist = Distance::Point_PointSq(pPoint->GetPos(), endPos);
  814.                                         if (fDist < fMinDist)
  815.                                         {
  816.                                                 fMinDist = fDist;
  817.                                                 itSelected = itUnit;
  818.                                                 index = i;
  819.                                         }
  820.                                 }
  821.                         }
  822.                         if (index > 0)
  823.                         {
  824.                                 CCCPOINT(CLeader_AssignFormationPoints_A);
  825.  
  826.                                 itSelected->m_FormationPointIndex = index;
  827.                                 pFormationOwner->m_pFormation->GetNewFormationPoint(itSelected->m_refUnit, index);
  828.                                 iAssignedCount++;
  829.                                 ;
  830.                         }
  831.                 }
  832.         }
  833.         // then re-assign the members who has found a single class point, but can find a free multiple class point closer to the owner
  834.         for (itUnit = m_pGroup->GetUnits().begin(); itUnit != itUnitEnd; ++itUnit)
  835.         {
  836.                 CUnitImg& unit = (*itUnit);
  837.                 //formation points are sorted by distance to point 0
  838.                 if (unit.m_refUnit == refAILeader && !bIncludeLeader)
  839.                         continue;
  840.  
  841.                 //              float fMinDist = 987654321.f;
  842.                 for (int i = 1; i < itUnit->m_FormationPointIndex; i++)
  843.                 {
  844.                         CAIObject* pPoint = pFormation->GetFormationPoint(i);
  845.                         if ((unit.GetProperties() & unitProp) && unit.m_refUnit != m_refFormationOwner
  846.                             && (unit.GetClass() & pFormation->GetPointClass(i)) && !pFormation->GetPointOwner(i))
  847.                         {
  848.                                 CCCPOINT(CLeader_AssignFormationPoints_B);
  849.  
  850.                                 int currentIndex = itUnit->m_FormationPointIndex;
  851.                                 pFormation->FreeFormationPoint(unit.m_refUnit);
  852.                                 pFormation->GetNewFormationPoint(unit.m_refUnit, i);
  853.                                 itUnit->m_FormationPointIndex = i;
  854.                         }
  855.                 }
  856.         }
  857.  
  858.         return iAssignedCount;
  859. }
  860.  
  861. bool CLeader::AssignFormationPoint(CUnitImg& unit, int teamSize, bool bAnyClass, bool bClosestToOwner)
  862. {
  863.         CAIObject* const pFormationOwner = m_refFormationOwner.GetAIObject();
  864.         CFormation* pFormation;
  865.  
  866.         CCCPOINT(CLeader_AssignFormationPoint);
  867.  
  868.         int myPointIndex = -1;
  869.         if (pFormationOwner && (pFormation = pFormationOwner->m_pFormation))
  870.         {
  871.                 if (bAnyClass)
  872.                         myPointIndex = pFormation->GetClosestPointIndex(unit.m_refUnit, true, teamSize, -1, bClosestToOwner);
  873.                 else
  874.                 {
  875.                         int myClass = unit.m_SoldierClass;
  876.                         if (myClass)
  877.                         {
  878.                                 myPointIndex = pFormation->GetClosestPointIndex(unit.m_refUnit, true, teamSize, myClass, bClosestToOwner);
  879.                         }
  880.                         if (myPointIndex < 0) // if your class is not found, try searching an undefined class point
  881.                         {
  882.                                 myPointIndex = pFormation->GetClosestPointIndex(unit.m_refUnit, true, teamSize, UNIT_CLASS_UNDEFINED, bClosestToOwner);
  883.                         }
  884.                 }
  885.         }
  886.  
  887.         if (myPointIndex >= 0)
  888.         {
  889.                 unit.m_FormationPointIndex = myPointIndex;
  890.                 return true;
  891.         }
  892.  
  893.         return false;
  894. }
  895.  
  896. void CLeader::AssignFormationPointIndex(CUnitImg& unit, int index)
  897. {
  898.         unit.m_FormationPointIndex = index;
  899.         CFormation* pFormation;
  900.         CAIObject* const pFormationOwner = m_refFormationOwner.GetAIObject();
  901.  
  902.         if (pFormationOwner && (pFormation = pFormationOwner->m_pFormation))
  903.         {
  904.                 CCCPOINT(CLeader_AssignFormationPointIndex);
  905.  
  906.                 pFormation->FreeFormationPoint(unit.m_refUnit);
  907.                 pFormation->GetNewFormationPoint(unit.m_refUnit, index);
  908.         }
  909. }
  910.  
  911. //
  912. //--------------------------------------------------------------------------------------------------------------
  913. CLeaderAction* CLeader::CreateAction(const LeaderActionParams* params, const char* signalText)
  914. {
  915.         CLeaderAction* pAction(NULL);
  916.  
  917.         switch (params->type)
  918.         {
  919.         case LA_ATTACK:
  920.                 switch (params->subType)
  921.                 {
  922.                 case LAS_ATTACK_SWITCH_POSITIONS:
  923.                         pAction = new CLeaderAction_Attack_SwitchPositions(this, *params);
  924.                         break;
  925.                 case LAS_DEFAULT:
  926.                 default:
  927.                         pAction = new CLeaderAction_Attack(this);
  928.                         break;
  929.                 }
  930.                 break;
  931.         case LA_SEARCH:
  932.                 pAction = new CLeaderAction_Search(this, *params);
  933.                 break;
  934.         default:
  935.                 AIAssert(!"Action type not added");
  936.         }
  937.         if (signalText)
  938.         {
  939.                 CAIObject* pAILeader = GetAssociation().GetAIObject();
  940.                 if (pAILeader)
  941.                         GetAISystem()->SendSignal(SIGNALFILTER_SENDER, 1, signalText, pAILeader);
  942.         }
  943.  
  944.         if (pAction)
  945.                 m_vMarkedPosition.Set(0, 0, 0);
  946.  
  947.         return pAction;
  948. }
  949.  
  950. //
  951. //--------------------------------------------------------------------------------------------------------------
  952. void CLeader::Serialize(TSerialize ser)
  953. {
  954.         // (MATT) There will be problems serialising the groupid and group pointer  {2009/03/31}
  955.  
  956.         ser.BeginGroup("AILeader");
  957.         {
  958.                 CAIActor::Serialize(ser);
  959.  
  960.                 m_refFormationOwner.Serialize(ser, "m_refFormationOwner");
  961.                 m_refFormationOwner.Serialize(ser, "m_refPrevFormationOwner");
  962.                 ser.Value("m_szFormationDescriptor", m_szFormationDescriptor);
  963.  
  964.                 ser.Value("m_vForcedPreferredPos", m_vForcedPreferredPos);
  965.  
  966.                 m_refEnemyTarget.Serialize(ser, "m_refEnemyTarget");
  967.  
  968.                 ser.Value("m_vMarkedPosition", m_vMarkedPosition);
  969.                 ser.Value("m_bLeaderAlive", m_bLeaderAlive);
  970.                 ser.Value("m_bKeepEnabled", m_bKeepEnabled);
  971.  
  972.                 ser.BeginGroup("m_pCurrentAction");
  973.                 {
  974.                         ELeaderAction actionType = ser.IsWriting() ? (m_pCurrentAction ? m_pCurrentAction->GetType() : LA_NONE) : LA_NONE;
  975.                         ELeaderActionSubType subType = ser.IsWriting() ? (m_pCurrentAction ? m_pCurrentAction->GetSubType() : LAS_DEFAULT) : LAS_DEFAULT;
  976.                         ser.EnumValue("ActionType", actionType, LA_NONE, LA_LAST);
  977.                         ser.EnumValue("ActionSubType", subType, LAS_DEFAULT, LAS_LAST);
  978.                         if (ser.IsReading())
  979.                         {
  980.                                 AbortExecution();//clears current action
  981.                                 if (actionType != LA_NONE)
  982.                                 {
  983.                                         LeaderActionParams params(actionType, subType);
  984.                                         m_pCurrentAction = CreateAction(&params);
  985.                                 }
  986.                         }
  987.  
  988.                         if (m_pCurrentAction)
  989.                                 m_pCurrentAction->Serialize(ser);
  990.                 }
  991.                 ser.EndGroup(); // ser.BeginGroup("m_pCurrentAction");
  992.         }
  993.         ser.EndGroup(); // ser.BeginGroup("AILeader");
  994. }
  995.  
  996. //
  997. //----------------------------------------------------------------------------------------------------------
  998.  
  999. void CLeader::AssignTargetToUnits(uint32 unitProp, int maxUnitsPerTarget)
  1000. {
  1001.  
  1002.         CAIGroup::TSetAIObjects::iterator itTarget = m_pGroup->GetTargets().begin();
  1003.         std::vector<int> AssignedUnits;
  1004.  
  1005.         int indexTarget = 0;
  1006.         const CAIObject* pTarget;
  1007.         int numUnits = m_pGroup->GetUnitCount(unitProp);
  1008.         int numtargets = m_pGroup->GetTargets().size();
  1009.  
  1010.         if (numtargets == 0)
  1011.                 numtargets = 1;
  1012.         for (int i = 0; i < numtargets; i++)
  1013.                 AssignedUnits.push_back(0);
  1014.  
  1015.         if (itTarget != m_pGroup->GetTargets().end())
  1016.                 pTarget = itTarget->GetAIObject();
  1017.         else
  1018.         {
  1019.                 pTarget = static_cast<CAIObject*>(GetAISystem()->GetBeacon(GetGroupId()));
  1020.                 if (!pTarget) // no beacon, no targets
  1021.                         return;
  1022.         }
  1023.  
  1024.         int unitsPerTarget = numUnits / numtargets;
  1025.         if (unitsPerTarget > maxUnitsPerTarget)
  1026.                 unitsPerTarget = maxUnitsPerTarget;
  1027.  
  1028.         for (TUnitList::iterator it = m_pGroup->GetUnits().begin(); it != m_pGroup->GetUnits().end(); ++it)
  1029.         {
  1030.                 CUnitImg& unit = *it;
  1031.                 if (unit.GetProperties() & unitProp)
  1032.                 {
  1033.                         AISignalExtraData data;
  1034.                         unit.ClearPlanning();
  1035.                         IEntity* pTargetEntity = NULL;
  1036.  
  1037.                         // (MATT) This casting is horrible at best, at worst might not work {2009/02/10}
  1038.                         if (const CPuppet* pPuppet = pTarget->CastToCPuppet())
  1039.                                 pTargetEntity = (IEntity*)pPuppet->GetAssociation().GetAIObject();
  1040.                         else if (const CAIPlayer* pPlayer = pTarget->CastToCAIPlayer())
  1041.                                 pTargetEntity = (IEntity*)pPlayer->GetAssociation().GetAIObject();
  1042.  
  1043.                         if (pTargetEntity)
  1044.                                 data.nID = pTargetEntity->GetId();
  1045.                         data.SetObjectName(pTarget->GetName());
  1046.  
  1047.                         CUnitAction* pAcquire = new CUnitAction(UA_ACQUIRETARGET, true, "", data);
  1048.                         unit.m_Plan.push_back(pAcquire);
  1049.                         unit.ExecuteTask();
  1050.                         AssignedUnits[indexTarget] = AssignedUnits[indexTarget] + 1;
  1051.                         if (AssignedUnits[indexTarget] >= unitsPerTarget)
  1052.                         {
  1053.                                 indexTarget++;
  1054.                                 if (indexTarget >= numtargets)
  1055.                                         break;
  1056.                                 if (itTarget != m_pGroup->GetTargets().end())
  1057.                                         ++itTarget;
  1058.                                 if (itTarget == m_pGroup->GetTargets().end())
  1059.                                         break;
  1060.                                 else
  1061.                                         pTarget = itTarget->GetAIObject();
  1062.                         }
  1063.  
  1064.                 }
  1065.         }
  1066.         UpdateEnemyStats();
  1067. }
  1068.  
  1069. int CLeader::GetActiveUnitPlanCount(uint32 unitProp) const
  1070. {
  1071.         int active = 0;
  1072.         for (TUnitList::const_iterator it = m_pGroup->GetUnits().begin(); it != m_pGroup->GetUnits().end(); ++it)
  1073.         {
  1074.                 const CUnitImg& unit = *it;
  1075.                 if ((unit.GetProperties() & unitProp) && !unit.m_Plan.empty())
  1076.                         active++;
  1077.         }
  1078.         return active;
  1079. }
  1080.  
  1081. //
  1082. //-------------------------------------------------------------------------------------
  1083.  
  1084. CAIObject* CLeader::GetEnemyLeader() const
  1085. {
  1086.         CWeakRef<CAIObject> refTarget = m_pGroup->GetAttentionTarget(true);
  1087.         CAIActor* pTarget = refTarget.GetIAIObject()->CastToCAIActor();
  1088.         CAIObject* pAILeader = NULL;
  1089.         if (pTarget)
  1090.         {
  1091.                 CLeader* pLeader = GetAISystem()->GetLeader(pTarget);
  1092.                 if (pLeader)
  1093.                         pAILeader = pLeader->GetAssociation().GetAIObject();
  1094.         }
  1095.         return pAILeader;
  1096. }
  1097.  
  1098. void CLeader::DeadUnitNotify(CAIActor* pAIObj)
  1099. {
  1100.         if (pAIObj && GetAssociation() == pAIObj)
  1101.         {
  1102.                 GetAISystem()->SendSignal(SIGNALFILTER_SUPERGROUP, 0, "OnLeaderDied", pAIObj);
  1103.                 m_bLeaderAlive = false;
  1104.         }
  1105.  
  1106.         if (m_pCurrentAction) m_pCurrentAction->DeadUnitNotify(pAIObj);
  1107.  
  1108. }
  1109.  
downloadLeader.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