BVB Source Codes

CRYENGINE Show GameObject.cpp Source code

Return Download CRYENGINE: download GameObject.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /*************************************************************************
  4.    -------------------------------------------------------------------------
  5.    $Id$
  6.    $DateTime$
  7.  
  8.    -------------------------------------------------------------------------
  9.    History:
  10.    - 6:9:2004   12:46 : Created by M谩rcio Martins
  11.  
  12. *************************************************************************/
  13. #include "StdAfx.h"
  14. #include "GameObjects/GameObject.h"
  15. #include "CryAction.h"
  16. #include "Network/GameContext.h"
  17. #include "Network/GameClientChannel.h"
  18. #include "Network/GameServerChannel.h"
  19. #include "Network/GameClientNub.h"
  20. #include "Network/GameServerNub.h"
  21. #include "Serialization/SerializeScriptTableWriter.h"
  22. #include "Serialization/SerializeScriptTableReader.h"
  23. #include "GameObjectSystem.h"
  24. #include <CrySystem/ITextModeConsole.h>
  25. #include "CryActionCVars.h"
  26.  
  27. #include <CryAISystem/IAIObject.h>
  28. #include <CryAISystem/IAIActorProxy.h>
  29.  
  30. // ugly: for GetMovementController()
  31. #include "IActorSystem.h"
  32. #include "IVehicleSystem.h"
  33.  
  34. #include <CryNetwork/INetwork.h>
  35.  
  36. //#pragma optimize("", off)
  37. //#pragma inline_depth(0)
  38.  
  39. #define GET_FLAG_FOR_SLOT(flag, slotbit)        (((flag) & (slotbit)) != 0)
  40. #define SET_FLAG_FOR_SLOT(flag, slotbit, value) if (value) { flag |= (slotbit); } else { flag &= ~slotbit; }
  41.  
  42. static const size_t MAX_REMOVING_EXTENSIONS = 16;
  43. //static const size_t MAX_ADDING_EXTENSIONS = 16;
  44. static const size_t NOT_IN_UPDATE_MODE = size_t(-1);
  45. static EntityId updatingEntity = 0;
  46. static size_t numRemovingExtensions = NOT_IN_UPDATE_MODE;
  47. static IGameObjectSystem::ExtensionID removingExtensions[MAX_REMOVING_EXTENSIONS];
  48. CGameObject::SExtension CGameObject::m_addingExtensions[CGameObject::MAX_ADDING_EXTENSIONS];
  49. int CGameObject::m_nAddingExtension = 0;
  50. CGameObjectSystem* CGameObject::m_pGOS = 0;
  51.  
  52. static const float UPDATE_TIMEOUT_HUGE = 1e20f;
  53. static const float DISTANCE_CHECKER_TIMEOUT = 1.3f;
  54. static const float FAR_AWAY_DISTANCE = 150.0f;
  55.  
  56. // MUST BE SYNCHRONIZED WITH EUpdateStates
  57. const float CGameObject::UpdateTimeouts[eUS_COUNT_STATES] =
  58. {
  59.         3.0f,                // eUS_Visible_Close
  60.         5.0f,                // eUS_Visible_FarAway
  61.         UPDATE_TIMEOUT_HUGE, // eUS_NotVisible_Close
  62.         UPDATE_TIMEOUT_HUGE, // eUS_NotVisible_FarAway
  63.         27.0f,               // eUS_CheckVisibility_Close
  64.         13.0f,               // eUS_CheckVisibility_FarAway
  65. };
  66. const char* CGameObject::UpdateNames[eUS_COUNT_STATES] =
  67. {
  68.         "Visible_Close",           // eUS_Visible_Close
  69.         "Visible_FarAway",         // eUS_Visible_FarAway
  70.         "NotVisible_Close",        // eUS_NotVisible_Close
  71.         "NotVisible_FarAway",      // eUS_NotVisible_FarAway
  72.         "CheckVisibility_Close",   // eUS_CheckVisibility_Close
  73.         "CheckVisibility_FarAway", // eUS_CheckVisibility_FarAway
  74. };
  75. const char* CGameObject::EventNames[eUSE_COUNT_EVENTS] =
  76. {
  77.         "BecomeVisible",
  78.         "BecomeClose",
  79.         "BecomeFarAway",
  80.         "Timeout",
  81. };
  82. const CGameObject::EUpdateState CGameObject::UpdateTransitions[eUS_COUNT_STATES][eUSE_COUNT_EVENTS] =
  83. {
  84.         /*
  85.            //eUS_CheckVisibility_FarAway:// {eUS_CheckVisibility_FarAway, eUS_CheckVisibility_FarAway, eUS_CheckVisibility_FarAway, eUS_CheckVisibility_FarAway}
  86.                                          {eUSE_BecomeVisible         , eUSE_BecomeClose           , eUSE_BecomeFarAway         , eUSE_Timeout               }
  87.          */
  88.         /*eUS_Visible_Close:*/           { eUS_INVALID,         eUS_Visible_Close,         eUS_Visible_FarAway,         eUS_CheckVisibility_Close   },
  89.         /*eUS_Visible_FarAway:*/         { eUS_INVALID,         eUS_Visible_Close,         eUS_Visible_FarAway,         eUS_CheckVisibility_FarAway },
  90.         /*eUS_NotVisible_Close:*/        { eUS_Visible_Close,   eUS_NotVisible_Close,      eUS_NotVisible_FarAway,      eUS_NotVisible_Close        },
  91.         /*eUS_NotVisible_FarAway:*/      { eUS_Visible_FarAway, eUS_NotVisible_Close,      eUS_NotVisible_FarAway,      eUS_NotVisible_FarAway      },
  92.         /*eUS_CheckVisibility_Close:*/   { eUS_Visible_Close,   eUS_CheckVisibility_Close, eUS_CheckVisibility_FarAway, eUS_NotVisible_Close        },
  93.         /*eUS_CheckVisibility_FarAway:*/ { eUS_Visible_FarAway, eUS_CheckVisibility_Close, eUS_CheckVisibility_FarAway, eUS_NotVisible_FarAway      },
  94. };
  95.  
  96. static int g_TextModeY = 0;
  97. static float g_y;
  98. static CTimeValue g_lastUpdate;
  99. static int g_showUpdateState = 0;
  100.  
  101. static AABB CreateDistanceAABB(Vec3 center, float radius = FAR_AWAY_DISTANCE)
  102. {
  103.         static const float CHECK_GRANULARITY = 2.0f;
  104.         Vec3 mn, mx;
  105.         for (int i = 0; i < 3; i++)
  106.         {
  107.                 center[i] = floor_tpl(center[i] / CHECK_GRANULARITY) * CHECK_GRANULARITY;
  108.                 mn[i] = center[i] - radius * 0.5f;
  109.                 mx[i] = center[i] + radius * 0.5f;
  110.         }
  111.         return AABB(mn, mx);
  112. }
  113.  
  114. static int g_forceFastUpdate = 0;
  115. static int g_visibilityTimeout = 0;
  116. static float g_visibilityTimeoutTime = 0.0f;
  117.  
  118. static std::set<CGameObject*> g_updateSchedulingProfile;
  119. static CryCriticalSection g_updateSchedulingProfileCritSec;
  120.  
  121. void CGameObject::CreateCVars()
  122. {
  123.         REGISTER_CVAR(g_forceFastUpdate, 0, VF_CHEAT, "GameObjects IsProbablyVisible->TRUE && IsProbablyDistant()->FALSE");
  124.         REGISTER_CVAR(g_visibilityTimeout, 0, VF_CHEAT, "Adds visibility timeout to IsProbablyVisible() calculations");
  125.         REGISTER_CVAR(g_visibilityTimeoutTime, 30.0f, VF_CHEAT, "Visibility timeout time used by IsProbablyVisible() calculations");
  126.         REGISTER_CVAR(g_showUpdateState, 0, VF_CHEAT, "Show the game object update state of any activated entities; 3-4 -- AI objects only");
  127. }
  128.  
  129. //------------------------------------------------------------------------
  130. CGameObject::CGameObject() :
  131.         m_pActionDelegate(0),
  132.         m_pViewDelegate(0),
  133.         m_pView(0),
  134.         m_pProfileManager(0),
  135. #if GAME_OBJECT_SUPPORTS_CUSTOM_USER_DATA
  136.         m_pUserData(0),
  137. #endif
  138.         m_channelId(0),
  139.         m_enabledAspects(NET_ASPECT_ALL),
  140.         m_delegatableAspects(NET_ASPECT_ALL),
  141.         m_enabledPhysicsEvents(0),
  142.         m_forceUpdate(0),
  143.         m_updateState(eUS_NotVisible_FarAway),
  144.         m_updateTimer(0.1f),
  145.         m_isBoundToNetwork(false),
  146.         m_inRange(false),
  147.         m_justExchanging(false),
  148.         m_aiMode(eGOAIAM_VisibleOrInRange),
  149.         m_physDisableMode(eADPM_Never),
  150.         m_prePhysicsUpdateRule(ePPU_Never),
  151.         m_bPrePhysicsEnabled(false),
  152.         m_pSchedulingProfiles(NULL),
  153.         m_predictionHandle(0),
  154.         m_bPhysicsDisabled(false),
  155.         m_bNoSyncPhysics(false),
  156.         m_bNeedsNetworkRebind(false),
  157.         m_bOnInitEventCalled(false),
  158.         m_cachedParentId(0)
  159. {
  160.         static_assert(eGFE_Last <= 64, "Unexpected enum value!");
  161.  
  162.         if (!m_pGOS)
  163.                 m_pGOS = (CGameObjectSystem*) CCryAction::GetCryAction()->GetIGameObjectSystem();
  164.  
  165.         for (int i = 0; i < NUM_ASPECTS; i++)
  166.                 m_profiles[i] = 255;
  167.  
  168.         m_bVisible = true;
  169. }
  170.  
  171. //------------------------------------------------------------------------
  172. CGameObject::~CGameObject()
  173. {
  174.         g_updateSchedulingProfile.erase(this);
  175. }
  176.  
  177. //------------------------------------------------------------------------
  178. ILINE bool CGameObject::TestIsProbablyVisible(uint state)
  179. {
  180.         if (g_forceFastUpdate)
  181.                 return false;
  182.  
  183.         switch (state)
  184.         {
  185.         case eUS_Visible_Close:
  186.         case eUS_Visible_FarAway:
  187.         case eUS_CheckVisibility_Close:
  188.         case eUS_CheckVisibility_FarAway:
  189.                 return true;
  190.         case eUS_NotVisible_FarAway:
  191.         case eUS_NotVisible_Close:
  192.                 return false;
  193.         }
  194.         CRY_ASSERT(false);
  195.         return false;
  196. }
  197.  
  198. //------------------------------------------------------------------------
  199. ILINE bool CGameObject::TestIsProbablyDistant(uint state)
  200. {
  201.         if (g_forceFastUpdate)
  202.                 return true;
  203.  
  204.         switch (state)
  205.         {
  206.         case eUS_Visible_FarAway:
  207.         case eUS_CheckVisibility_FarAway:
  208.         case eUS_NotVisible_FarAway:
  209.                 return true;
  210.         case eUS_CheckVisibility_Close:
  211.         case eUS_Visible_Close:
  212.         case eUS_NotVisible_Close:
  213.                 return false;
  214.         }
  215.         CRY_ASSERT(false);
  216.         return false;
  217. }
  218.  
  219. //------------------------------------------------------------------------
  220. bool CGameObject::IsProbablyVisible()
  221. {
  222.         // this would be a case of driver in a tank - hidden, but needes to be updated
  223.         if (GetEntity()->IsHidden() && (GetEntity()->GetFlags() & ENTITY_FLAG_UPDATE_HIDDEN))
  224.                 return true;
  225.  
  226.         if (GetEntity()->IsHidden())
  227.                 return false;
  228.  
  229.         if (g_visibilityTimeout)
  230.         {
  231.                 IEntityRender* pProxy = GetEntity()->GetRenderInterface();
  232.                 if (pProxy)
  233.                 {
  234.                         float fDiff = gEnv->pTimer->GetCurrTime() - pProxy->GetLastSeenTime();
  235.                         if (fDiff > g_visibilityTimeoutTime)
  236.                         {
  237.                                 if (m_bVisible)
  238.                                 {
  239.                                         if (g_visibilityTimeout == 2)
  240.                                                 CryLogAlways("Entity %s not visible for %f seconds - visibility timeout", GetEntity()->GetName(), fDiff);
  241.                                 }
  242.                                 m_bVisible = false;
  243.                                 return (false);
  244.                         }
  245.                 }
  246.         }
  247.  
  248.         if (!m_bVisible)
  249.         {
  250.                 if (g_visibilityTimeout == 2)
  251.                         CryLogAlways("Entity %s is now visible again after visibility timeout", GetEntity()->GetName());
  252.         }
  253.         m_bVisible = true;
  254.  
  255.         return TestIsProbablyVisible(m_updateState);
  256. }
  257.  
  258. //------------------------------------------------------------------------
  259. bool CGameObject::IsProbablyDistant()
  260. {
  261.         //it's hidden - far away
  262.         if (GetEntity()->IsHidden() && !(GetEntity()->GetFlags() & ENTITY_FLAG_UPDATE_HIDDEN))
  263.                 return true;
  264.  
  265.         if (g_visibilityTimeout)
  266.         {
  267.                 if (!m_bVisible)
  268.                         return (true);
  269.         }
  270.         return TestIsProbablyDistant(m_updateState);
  271. }
  272.  
  273. //------------------------------------------------------------------------
  274. void CGameObject::UpdateStateEvent(EUpdateStateEvent evt)
  275. {
  276.         EUpdateState newState = UpdateTransitions[m_updateState][evt];
  277.  
  278.         if (newState >= eUS_INVALID)
  279.         {
  280.                 //GameWarning("%s: visibility activation requested invalid state (%s on event %s)", GetEntity()->GetName(), UpdateNames[m_updateState], EventNames[m_updateState] );
  281.                 return;
  282.         }
  283.  
  284.         if (newState != m_updateState)
  285.         {
  286.                 if (TestIsProbablyVisible(newState) && !TestIsProbablyVisible(m_updateState))
  287.                 {
  288.                         SGameObjectEvent goe(eGFE_OnBecomeVisible, eGOEF_ToExtensions);
  289.                         SendEvent(goe);
  290.                 }
  291.  
  292.                 m_updateState = newState;
  293.                 m_updateTimer = UpdateTimeouts[m_updateState];
  294.  
  295.                 uint32 flags = m_pEntity->GetFlags();
  296.                 if (UpdateTransitions[m_updateState][eUSE_BecomeVisible] != eUS_INVALID)
  297.                         flags |= ENTITY_FLAG_SEND_RENDER_EVENT;
  298.                 else
  299.                         flags &= ~ENTITY_FLAG_SEND_RENDER_EVENT;
  300.                 m_pEntity->SetFlags(flags);
  301.  
  302.                 EvaluateUpdateActivation();
  303.         }
  304. }
  305.  
  306. //------------------------------------------------------------------------
  307. bool CGameObject::ShouldUpdateSlot(const SExtension* pExt, uint32 slot, uint32 slotbit, bool checkAIDisable)
  308. {
  309.         if (checkAIDisable)
  310.                 if (GET_FLAG_FOR_SLOT(pExt->flagDisableWithAI, slotbit))
  311.                         return false;
  312.  
  313.         if (pExt->forceEnables[slot])
  314.                 return true;
  315.  
  316.         if (GET_FLAG_FOR_SLOT(pExt->flagNeverUpdate, slotbit))
  317.                 return false;
  318.  
  319.         if (!pExt->updateEnables[slot])
  320.                 return false;
  321.  
  322.         bool visibleCheck = true;
  323.         if (GET_FLAG_FOR_SLOT(pExt->flagUpdateWhenVisible, slotbit))
  324.                 visibleCheck = TestIsProbablyVisible(m_updateState);
  325.  
  326.         bool inRangeCheck = true;
  327.         if (GET_FLAG_FOR_SLOT(pExt->flagUpdateWhenInRange, slotbit))
  328.                 inRangeCheck = !TestIsProbablyDistant(m_updateState);
  329.  
  330.         if (GET_FLAG_FOR_SLOT(pExt->flagUpdateCombineOr, slotbit))
  331.                 return visibleCheck || inRangeCheck;
  332.         else
  333.                 return visibleCheck && inRangeCheck;
  334. }
  335.  
  336. //------------------------------------------------------------------------
  337. void CGameObject::Initialize()
  338. {
  339.         m_entityId = m_pEntity->GetId();
  340.  
  341.         m_pSchedulingProfiles = ((CGameObjectSystem*)CCryAction::GetCryAction()->GetIGameObjectSystem())->GetEntitySchedulerProfiles(m_pEntity);
  342.  
  343.         GetEntity()->SetFlags(GetEntity()->GetFlags() | ENTITY_FLAG_SEND_RENDER_EVENT);
  344. }
  345.  
  346. //////////////////////////////////////////////////////////////////////////
  347. void CGameObject::OnInitEvent()
  348. {
  349.         if (m_bOnInitEventCalled)
  350.                 return;
  351.  
  352.         m_bOnInitEventCalled = true;
  353.         IGameObjectSystem* pGOS = m_pGOS;
  354.  
  355.         if (!m_extensions.empty())
  356.         {
  357.                 TExtensions preExtensions;
  358.                 m_extensions.swap(preExtensions);
  359.                 // this loop repopulates m_extensions
  360.                 for (TExtensions::const_iterator iter = preExtensions.begin(); iter != preExtensions.end(); ++iter)
  361.                 {
  362.                         auto *pParams = m_pUserData ?
  363.                                 static_cast<IGameObjectSystem::SEntitySpawnParamsForGameObjectWithPreactivatedExtension*>(m_pUserData) : nullptr;
  364.  
  365.                         const char* szExtensionName = pGOS->GetName(iter->id);
  366.                         if (!ChangeExtension(szExtensionName, eCE_Activate, pParams ? pParams->pSpawnSerializer : nullptr))
  367.                         {
  368.                                 if (szExtensionName)
  369.                                 {
  370.                                         gEnv->pLog->LogError("[GameObject]: Couldn't activate extension %s", szExtensionName);
  371.                                 }
  372.                                 //return false;
  373.                         }
  374.                 }
  375.  
  376.                 // set sticky bits, clear activated bits (extensions activated before initialization are sticky)
  377.                 for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  378.                 {
  379.                         iter->sticky = iter->activated;
  380.                         iter->activated = false;
  381.                 }
  382.         }
  383. }
  384.  
  385. bool CGameObject::BindToNetwork(EBindToNetworkMode mode)
  386. {
  387.         return BindToNetworkWithParent(mode, 0);
  388. }
  389.  
  390. bool CGameObject::BindToNetworkWithParent(EBindToNetworkMode mode, EntityId parentId)
  391. {
  392.         CGameContext* pGameContext = CCryAction::GetCryAction()->GetGameContext();
  393.         if (!pGameContext)
  394.                 return false;
  395.         INetContext* pNetContext = pGameContext->GetNetContext();
  396.         if (!pNetContext)
  397.                 return false;
  398.  
  399.         if (m_isBoundToNetwork)
  400.         {
  401.                 switch (mode)
  402.                 {
  403.                 case eBTNM_NowInitialized:
  404.                         if (!m_isBoundToNetwork)
  405.                                 return false;
  406.                         CRY_ASSERT(parentId == 0);
  407.                         parentId = m_cachedParentId;
  408.                 // fall through
  409.                 case eBTNM_Force:
  410.                         m_isBoundToNetwork = false;
  411.                         break;
  412.                 case eBTNM_Normal:
  413.                         return true;
  414.                 }
  415.         }
  416.         else if (mode == eBTNM_NowInitialized)
  417.                 return false;
  418.  
  419.         if (GetEntity()->GetFlags() & (ENTITY_FLAG_CLIENT_ONLY | ENTITY_FLAG_SERVER_ONLY))
  420.                 return false;
  421.  
  422.         if (!GetEntity()->IsInitialized())
  423.         {
  424.                 m_cachedParentId = parentId;
  425.                 m_isBoundToNetwork = true;
  426.                 return true;
  427.         }
  428.  
  429.         static const NetworkAspectType gameObjectAspects =
  430.           eEA_GameClientDynamic |
  431.           eEA_GameServerDynamic |
  432.           eEA_GameClientStatic |
  433.           eEA_GameServerStatic |
  434.           eEA_Aspect31 |
  435.           eEA_GameClientA |
  436.           eEA_GameServerA |
  437.           eEA_GameClientB |
  438.           eEA_GameServerB |
  439.           eEA_GameClientC |
  440.           eEA_GameServerC |
  441.           eEA_GameClientD |
  442.           eEA_GameClientE |
  443.           eEA_GameClientF |
  444.           eEA_GameClientG |
  445.           eEA_GameClientH |
  446.           eEA_GameClientI |
  447.           eEA_GameClientJ |
  448.           eEA_GameClientK |
  449.           eEA_GameServerD |
  450.           eEA_GameClientL |
  451.           eEA_GameClientM |
  452.           eEA_GameClientN |
  453.           eEA_GameClientO |
  454.           eEA_GameClientP |
  455.           eEA_GameServerE;
  456.  
  457.         NetworkAspectType aspects = gameObjectAspects;
  458.         INetChannel* pControllingChannel = NULL;
  459.  
  460.         if (!m_bNoSyncPhysics && (GetEntity()->GetPhysicalEntity() || m_pProfileManager))
  461.         {
  462.                 aspects |= eEA_Physics;
  463.                 //              aspects &= ~eEA_Volatile;
  464.         }
  465.         if (GetEntity()->GetProxy(ENTITY_PROXY_SCRIPT))
  466.                 aspects |= eEA_Script;
  467.  
  468.         if (gEnv->bServer)
  469.         {
  470.                 if (m_channelId)
  471.                 {
  472.                         CGameServerNub* pServerNub = CCryAction::GetCryAction()->GetGameServerNub();
  473.                         if (!pServerNub)
  474.                         {
  475.                                 GameWarning("Unable to bind object to network (%s)", GetEntity()->GetName());
  476.                                 return false;
  477.                         }
  478.                         CGameServerChannel* pServerChannel = pServerNub->GetChannel(m_channelId);
  479.                         if (!pServerChannel)
  480.                         {
  481.                                 GameWarning("Unable to bind object to network (%s)", GetEntity()->GetName());
  482.                                 return false;
  483.                         }
  484.                         pServerChannel->SetPlayerId(GetEntity()->GetId());
  485.                         pControllingChannel = pServerChannel->GetNetChannel();
  486.                 }
  487.  
  488.                 bool isStatic = CCryAction::GetCryAction()->IsInLevelLoad();
  489.                 if (GetEntity()->GetFlags() & ENTITY_FLAG_NEVER_NETWORK_STATIC)
  490.                         isStatic = false;
  491.  
  492.                 aspects &= GetNetSerializeAspects();
  493.  
  494.                 pNetContext->BindObject(GetEntityId(), parentId, aspects, isStatic);
  495.                 pNetContext->SetDelegatableMask(GetEntityId(), m_delegatableAspects);
  496.                 if (pControllingChannel)
  497.                 {
  498.                         //pNetContext->DelegateAuthority( GetEntityId(), pControllingChannel );
  499.                 }
  500.         }
  501.  
  502.         // will this work :)
  503.         if (pControllingChannel)
  504.         {
  505.                 pControllingChannel->DeclareWitness(GetEntityId());
  506.         }
  507.  
  508.         m_isBoundToNetwork = true;
  509.         {
  510.                 AUTO_LOCK(g_updateSchedulingProfileCritSec);
  511.                 g_updateSchedulingProfile.insert(this);
  512.         }
  513.         EvaluateUpdateActivation();
  514.  
  515.         return true;
  516. }
  517.  
  518. bool CGameObject::IsAspectDelegatable(NetworkAspectType aspect)
  519. {
  520.         return (m_delegatableAspects & aspect) ? true : false;
  521. }
  522.  
  523. //------------------------------------------------------------------------
  524. void CGameObject::OnShutDown()
  525. {
  526.         // cannot release extensions while Physics is in a CB.
  527.         AcquireMutex();
  528.  
  529.         // Before deleting the extension, disable receiving any physics events.
  530.         // Mutex prevents
  531.         m_enabledPhysicsEvents = 0;
  532.  
  533.         FlushExtensions(true);
  534.         m_pGOS->SetPostUpdate(this, false);
  535.         m_distanceChecker.Reset();
  536.         g_updateSchedulingProfile.erase(this);
  537.  
  538.         ReleaseMutex();
  539. }
  540.  
  541. //------------------------------------------------------------------------
  542. void CGameObject::Release()
  543. {
  544.         delete this;
  545. }
  546.  
  547. //------------------------------------------------------------------------
  548. void CGameObject::DebugUpdateState()
  549. {
  550.         ITextModeConsole* pTMC = GetISystem()->GetITextModeConsole();
  551.  
  552.         float white[] = { 1, 1, 1, 1 };
  553.  
  554.         char buf[512];
  555.         char* pOut = buf;
  556.  
  557.         pOut += sprintf(pOut, "%s: %s", GetEntity()->GetName(), UpdateNames[m_updateState]);
  558.         if (m_updateTimer < (0.5f * UPDATE_TIMEOUT_HUGE))
  559.                 pOut += sprintf(pOut, " timeout:%.2f", m_updateTimer);
  560.         if (ShouldUpdateAI())
  561.                 pOut += sprintf(pOut, m_aiMode == eGOAIAM_Always ? "AI_ALWAYS" : " AIACTIVE");
  562.         if (m_bPrePhysicsEnabled)
  563.                 pOut += sprintf(pOut, " PREPHYSICS");
  564.         if (m_prePhysicsUpdateRule != ePPU_Never)
  565.                 pOut += sprintf(pOut, " pprule=%s", m_prePhysicsUpdateRule == ePPU_Always ? "always" : "whenai");
  566.         if (m_forceUpdate)
  567.                 pOut += sprintf(pOut, " force:%d", m_forceUpdate);
  568.         if (m_physDisableMode != eADPM_Never)
  569.                 pOut += sprintf(pOut, " physDisable:%d", m_physDisableMode);
  570.         IRenderAuxText::Draw2dLabel(10, g_y += 10, 1, white, false, "%s", buf);
  571.         if (pTMC)
  572.                 pTMC->PutText(0, g_TextModeY++, buf);
  573.  
  574.         if (g_showUpdateState == 2)
  575.         {
  576.                 bool checkAIDisable = !ShouldUpdateAI() && GetEntity()->GetAI();
  577.                 for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  578.                 {
  579.                         uint slotbit = 1;
  580.  
  581.                         for (int slot = 0; slot < MAX_UPDATE_SLOTS_PER_EXTENSION; slot++)
  582.                         {
  583.                                 pOut = buf;
  584.                                 pOut += sprintf(pOut, "%s[%d]: en:%u", m_pGOS->GetName(iter->id), slot, iter->updateEnables[slot]);
  585.  
  586.                                 if (iter->forceEnables[slot])
  587.                                         pOut += sprintf(pOut, " force:%d", int(iter->forceEnables[slot]));
  588.  
  589.                                 bool done = false;
  590.                                 if (checkAIDisable)
  591.                                         if (done = GET_FLAG_FOR_SLOT(iter->flagDisableWithAI, slotbit))
  592.                                                 pOut += sprintf(pOut, " ai-disable");
  593.  
  594.                                 if (!done && (done = GET_FLAG_FOR_SLOT(iter->flagNeverUpdate, slotbit)))
  595.                                         pOut += sprintf(pOut, " never");
  596.  
  597.                                 if (!done)
  598.                                 {
  599.                                         bool visibleCheck = true;
  600.                                         if (GET_FLAG_FOR_SLOT(iter->flagUpdateWhenVisible, slotbit))
  601.                                                 visibleCheck = TestIsProbablyVisible(m_updateState);
  602.  
  603.                                         bool inRangeCheck = true;
  604.                                         if (GET_FLAG_FOR_SLOT(iter->flagUpdateWhenInRange, slotbit))
  605.                                                 inRangeCheck = !TestIsProbablyDistant(m_updateState);
  606.  
  607.                                         pOut += sprintf(pOut, " %s", visibleCheck ? "visible" : "!visible");
  608.                                         if (GET_FLAG_FOR_SLOT(iter->flagUpdateCombineOr, slotbit))
  609.                                                 pOut += sprintf(pOut, " ||");
  610.                                         else
  611.                                                 pOut += sprintf(pOut, " &&");
  612.                                         pOut += sprintf(pOut, " %s", inRangeCheck ? "in-range" : "!in-range");
  613.                                 }
  614.                                 if (ShouldUpdateSlot(&*iter, slot, slotbit, checkAIDisable))
  615.                                 {
  616.                                         IRenderAuxText::Draw2dLabel(20, g_y += 10, 1, white, false, "%s", buf);
  617.                                         if (pTMC)
  618.                                                 pTMC->PutText(1, g_TextModeY++, buf);
  619.                                 }
  620.  
  621.                                 slotbit <<= 1;
  622.                         }
  623.                 }
  624.         }
  625. }
  626.  
  627. //------------------------------------------------------------------------
  628. void CGameObject::Update(SEntityUpdateContext& ctx)
  629. {
  630.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  631.  
  632.         if (gEnv->pTimer->GetFrameStartTime() != g_lastUpdate)
  633.         {
  634.                 g_lastUpdate = gEnv->pTimer->GetFrameStartTime();
  635.                 g_y = 10;
  636.                 g_TextModeY = 0;
  637.         }
  638.  
  639.         CRY_ASSERT(numRemovingExtensions == NOT_IN_UPDATE_MODE);
  640.         CRY_ASSERT(updatingEntity == 0);
  641.         numRemovingExtensions = 0;
  642.         m_nAddingExtension = 0;
  643.         updatingEntity = GetEntityId();
  644.  
  645.         m_distanceChecker.Update(*this, ctx.fFrameTime);
  646.  
  647.         m_updateTimer -= ctx.fFrameTime;
  648.         if (m_updateTimer < 0.0f)
  649.         {
  650.                 // be pretty sure that we won't trigger twice...
  651.                 m_updateTimer = UPDATE_TIMEOUT_HUGE;
  652.                 UpdateStateEvent(eUSE_Timeout);
  653.         }
  654.  
  655.         if (g_showUpdateState)
  656.         {
  657.                 DebugUpdateState();
  658.         }
  659.  
  660.         /*
  661.          * UPDATE EXTENSIONS
  662.          */
  663. #ifdef _DEBUG
  664.         IGameObjectSystem* pGameObjectSystem = m_pGOS;
  665. #endif
  666.         bool shouldUpdateAI = ShouldUpdateAI();
  667.         bool keepUpdating = shouldUpdateAI;
  668.         bool checkAIDisableOnSlots = !shouldUpdateAI && GetEntity()->GetAI();
  669.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  670.         {
  671. #ifdef _DEBUG
  672.                 const char* name = pGameObjectSystem->GetName(iter->id);
  673. #endif
  674.                 uint32 slotbit = 1;
  675.                 for (uint32 i = 0; i < MAX_UPDATE_SLOTS_PER_EXTENSION; ++i)
  676.                 {
  677.                         iter->forceEnables[i] -= iter->forceEnables[i] != 0;
  678.                         if (ShouldUpdateSlot(&*iter, i, slotbit, checkAIDisableOnSlots))
  679.                         {
  680.                                 iter->pExtension->Update(ctx, i);
  681.                                 keepUpdating = true;
  682.                         }
  683.  
  684.                         slotbit <<= 1;
  685.                 }
  686.         }
  687.  
  688.         if (!keepUpdating && m_forceUpdate <= 0)
  689.                 SetActivation(false);
  690.  
  691.         /*
  692.          * REMOVE EXTENSIONS
  693.          */
  694.         while (numRemovingExtensions)
  695.         {
  696.                 for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  697.                 {
  698.                         if (iter->id == removingExtensions[numRemovingExtensions - 1])
  699.                         {
  700.                                 RemoveExtension(iter);
  701.                                 break;
  702.                         }
  703.                 }
  704.  
  705.                 numRemovingExtensions--;
  706.         }
  707.         /*
  708.          * ADD EXTENSIONS
  709.          */
  710.         for (int i = 0; i < m_nAddingExtension; i++)
  711.                 m_extensions.push_back(m_addingExtensions[i]);
  712.         if (0 < m_nAddingExtension)
  713.         {
  714.                 std::sort(m_extensions.begin(), m_extensions.end());
  715.                 ClearCache();
  716.         }
  717.         for (int i = 0; i < m_nAddingExtension; i++)
  718.         {
  719.                 m_addingExtensions[i].pExtension->PostInit(this);
  720.                 m_addingExtensions[i] = SExtension();
  721.         }
  722.         m_nAddingExtension = 0;
  723.  
  724.         CRY_ASSERT(numRemovingExtensions != NOT_IN_UPDATE_MODE);
  725.         CRY_ASSERT(updatingEntity == GetEntityId());
  726.         numRemovingExtensions = NOT_IN_UPDATE_MODE;
  727.         updatingEntity = 0;
  728. }
  729.  
  730. void CGameObject::UpdateSchedulingProfile()
  731. {
  732.         bool remove = false;
  733.         if (m_isBoundToNetwork && m_pSchedulingProfiles)
  734.         {
  735.                 // We need to check NetContext here, because it's NULL in a dummy editor game session (or at least while starting up the editor).
  736.                 INetContext* pNetContext = CCryAction::GetCryAction()->GetGameContext()->GetNetContext();
  737.                 if (pNetContext && pNetContext->SetSchedulingParams(GetEntityId(), m_pSchedulingProfiles->normal, m_pSchedulingProfiles->owned))
  738.                         remove = true;
  739.         }
  740.         else
  741.         {
  742.                 remove = true;
  743.         }
  744.         if (remove)
  745.         {
  746.                 g_updateSchedulingProfile.erase(this);
  747.         }
  748. }
  749.  
  750. void CGameObject::UpdateSchedulingProfiles()
  751. {
  752.         AUTO_LOCK(g_updateSchedulingProfileCritSec);
  753.         for (std::set<CGameObject*>::iterator it = g_updateSchedulingProfile.begin(); it != g_updateSchedulingProfile.end(); )
  754.         {
  755.                 std::set<CGameObject*>::iterator next = it;
  756.                 ++next;
  757.                 (*it)->UpdateSchedulingProfile();
  758.                 it = next;
  759.         }
  760. }
  761.  
  762. void CGameObject::ForceUpdateExtension(IGameObjectExtension* pExt, int slot)
  763. {
  764.         SExtension* pInfo = GetExtensionInfo(pExt);
  765.         if (pInfo)
  766.         {
  767.                 pInfo->forceEnables[slot] = 255;
  768.                 SetActivation(true);
  769.         }
  770. }
  771.  
  772. //------------------------------------------------------------------------
  773. void CGameObject::ProcessEvent(SEntityEvent& event)
  774. {
  775.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  776.  
  777.         if (m_pEntity)
  778.         {
  779.                 switch (event.event)
  780.                 {
  781.                 case ENTITY_EVENT_UPDATE:
  782.                         {
  783.                                 SEntityUpdateContext* pCtx = (SEntityUpdateContext*)event.nParam[0];
  784.                                 Update(*pCtx);
  785.                         }
  786.                         break;
  787.                 case ENTITY_EVENT_RENDER_VISIBILITY_CHANGE:
  788.                         {
  789.                                 bool bVisible = event.nParam[0] != 0;
  790.                                 if (bVisible)
  791.                                 {
  792.                                         // Get distance of entity from camera.
  793.                                         float distanceFromCamera = GetEntity()->GetPos().GetDistance(GetISystem()->GetViewCamera().GetPosition());
  794.                                         m_updateState = (distanceFromCamera < FAR_AWAY_DISTANCE) ? eUS_CheckVisibility_Close : eUS_CheckVisibility_FarAway;
  795.  
  796.                                         UpdateStateEvent(eUSE_BecomeVisible);
  797.                                 }
  798.                         }
  799.                         break;
  800.  
  801.                 case ENTITY_EVENT_INIT:
  802.                         OnInitEvent();
  803.                         if (m_bNeedsNetworkRebind)
  804.                         {
  805.                                 m_bNeedsNetworkRebind = false;
  806.                                 BindToNetwork(eBTNM_Force);
  807.                         }
  808.                         break;
  809.                 case ENTITY_EVENT_RESET:
  810.                         if (m_bNeedsNetworkRebind)
  811.                         {
  812.                                 m_bNeedsNetworkRebind = false;
  813.                                 BindToNetwork(eBTNM_Force);
  814.                         }
  815.                         break;
  816.                 case ENTITY_EVENT_ENTERAREA:
  817.                         {
  818.                                 const EntityId distanceCheckerTrigger = m_distanceChecker.GetDistanceChecker();
  819.                                 if (distanceCheckerTrigger && event.nParam[2] == distanceCheckerTrigger)
  820.                                 {
  821.                                         if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity((EntityId)event.nParam[0]))
  822.                                         {
  823.                                                 if (CGameObject* pObj = (CGameObject*) pEntity->GetProxy(ENTITY_PROXY_USER))
  824.                                                 {
  825.                                                         if (!pObj->m_inRange)
  826.                                                         {
  827.                                                                 pObj->m_inRange = true;
  828.                                                                 pObj->UpdateStateEvent(eUSE_BecomeClose);
  829.                                                         }
  830.                                                 }
  831.                                         }
  832.                                 }
  833.                         }
  834.                         break;
  835.  
  836.                 case ENTITY_EVENT_LEAVEAREA:
  837.                         {
  838.                                 const EntityId distanceCheckerTrigger = m_distanceChecker.GetDistanceChecker();
  839.                                 if (distanceCheckerTrigger && event.nParam[2] == distanceCheckerTrigger)
  840.                                 {
  841.                                         if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity((EntityId)event.nParam[0]))
  842.                                         {
  843.                                                 if (CGameObject* pObj = (CGameObject*) pEntity->GetProxy(ENTITY_PROXY_USER))
  844.                                                 {
  845.                                                         if (pObj->m_inRange)
  846.                                                         {
  847.                                                                 pObj->m_inRange = false;
  848.                                                                 if (pObj->m_inRange == 0)
  849.                                                                         pObj->UpdateStateEvent(eUSE_BecomeFarAway);
  850.                                                         }
  851.                                                 }
  852.                                         }
  853.                                 }
  854.                         }
  855.                         break;
  856.  
  857.                 case ENTITY_EVENT_POST_SERIALIZE:
  858.                         PostSerialize();
  859.                         break;
  860.  
  861.                 case ENTITY_EVENT_DONE:
  862.                         if (m_isBoundToNetwork)
  863.                         {
  864.                                 // check if we're still bound
  865.                                 CGameContext* pGameContext = CCryAction::GetCryAction()->GetGameContext();
  866.                                 if (pGameContext)
  867.                                 {
  868.                                         INetContext* pNetContext = pGameContext->GetNetContext();
  869.                                         if (pNetContext)
  870.                                         {
  871.                                                 m_isBoundToNetwork = pNetContext->IsBound(GetEntityId());
  872.                                                 m_bNeedsNetworkRebind = !m_isBoundToNetwork;
  873.                                         }
  874.                                 }
  875.                         }
  876.                         break;
  877.                 case ENTITY_EVENT_HIDE:
  878.                 case ENTITY_EVENT_UNHIDE:
  879.                         EvaluateUpdateActivation();
  880.                         break;
  881.                 }
  882.  
  883.                 if (IAIObject* aiObject = m_pEntity->GetAI())
  884.                         aiObject->EntityEvent(event);
  885.  
  886.                 // Events to extensions are sent by Entity system as they are EntityComponents
  887.                 /*
  888.                    for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  889.                    {
  890.                    iter->pExtension->ProcessEvent(event);
  891.                    }
  892.                  */
  893.         }
  894. }
  895.  
  896. uint64 CGameObject::GetEventMask() const
  897. {
  898.         return
  899.           BIT64(ENTITY_EVENT_INIT) |
  900.                 BIT64(ENTITY_EVENT_RESET) |
  901.           BIT64(ENTITY_EVENT_DONE) |
  902.           BIT64(ENTITY_EVENT_UPDATE) |
  903.           BIT64(ENTITY_EVENT_RENDER_VISIBILITY_CHANGE) |
  904.           BIT64(ENTITY_EVENT_ENTERAREA) |
  905.           BIT64(ENTITY_EVENT_LEAVEAREA) |
  906.           BIT64(ENTITY_EVENT_POST_SERIALIZE) |
  907.           BIT64(ENTITY_EVENT_HIDE) |
  908.           BIT64(ENTITY_EVENT_UNHIDE);
  909. }
  910.  
  911. //------------------------------------------------------------------------
  912. IGameObjectExtension* CGameObject::GetExtensionWithRMIBase(const void* pBase)
  913. {
  914.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  915.         {
  916.                 if (iter->pExtension->GetRMIBase() == pBase)
  917.                         return iter->pExtension;
  918.         }
  919.         return nullptr;
  920. }
  921.  
  922. //------------------------------------------------------------------------
  923. bool CGameObject::CaptureActions(IActionListener* pAL)
  924. {
  925.         if (m_pActionDelegate || !pAL)
  926.                 return false;
  927.         m_pActionDelegate = pAL;
  928.         return true;
  929. }
  930.  
  931. bool CGameObject::CaptureView(IGameObjectView* pGOV)
  932. {
  933.         if (m_pViewDelegate || !pGOV)
  934.                 return false;
  935.         m_pViewDelegate = pGOV;
  936.  
  937.         if (m_pView == nullptr)
  938.         {
  939.                 m_pView = gEnv->pGameFramework->GetIViewSystem()->CreateView();
  940.                 m_pView->LinkTo(this);
  941.         }
  942.  
  943.         gEnv->pGameFramework->GetIViewSystem()->SetActiveView(m_pView);
  944.  
  945.         return true;
  946. }
  947.  
  948. bool CGameObject::CaptureProfileManager(IGameObjectProfileManager* pPM)
  949. {
  950.         if (m_pProfileManager || !pPM)
  951.                 return false;
  952.         m_pProfileManager = pPM;
  953.         return true;
  954. }
  955.  
  956. void CGameObject::ReleaseActions(IActionListener* pAL)
  957. {
  958.         if (m_pActionDelegate != pAL)
  959.                 return;
  960.         m_pActionDelegate = 0;
  961. }
  962.  
  963. void CGameObject::ReleaseView(IGameObjectView* pGOV)
  964. {
  965.         if (m_pViewDelegate != pGOV)
  966.                 return;
  967.         m_pViewDelegate = 0;
  968. }
  969.  
  970. void CGameObject::ReleaseProfileManager(IGameObjectProfileManager* pPM)
  971. {
  972.         if (m_pProfileManager != pPM)
  973.                 return;
  974.         m_pProfileManager = 0;
  975. }
  976.  
  977. //------------------------------------------------------------------------
  978. void CGameObject::UpdateView(SViewParams& viewParams)
  979. {
  980.         if (m_pViewDelegate)
  981.                 m_pViewDelegate->UpdateView(viewParams);
  982. }
  983.  
  984. //------------------------------------------------------------------------
  985. void CGameObject::PostUpdateView(SViewParams& viewParams)
  986. {
  987.         if (m_pViewDelegate)
  988.                 m_pViewDelegate->PostUpdateView(viewParams);
  989. }
  990.  
  991. //------------------------------------------------------------------------
  992. void CGameObject::OnAction(const ActionId& actionId, int activationMode, float value)
  993. {
  994.         if (m_pActionDelegate)
  995.                 m_pActionDelegate->OnAction(actionId, activationMode, value);
  996.         //      else
  997.         //              GameWarning("Action sent to an entity that doesn't implement action-listener; entity class is %s, and action is %s",GetEntity()->GetClass()->GetName(), actionId.c_str());
  998. }
  999.  
  1000. void CGameObject::AfterAction()
  1001. {
  1002.         if (m_pActionDelegate)
  1003.                 m_pActionDelegate->AfterAction();
  1004. }
  1005.  
  1006. //////////////////////////////////////////////////////////////////////////
  1007. bool CGameObject::NeedGameSerialize()
  1008. {
  1009.         return true;
  1010. }
  1011.  
  1012. static const char* AspectProfileSerializationName(int i)
  1013. {
  1014.         static char buffer[11] = { 0 };
  1015.  
  1016.         if (!buffer[0])
  1017.         {
  1018.                 buffer[0] = 'a';
  1019.                 buffer[1] = 'p';
  1020.                 buffer[2] = 'r';
  1021.                 buffer[3] = 'o';
  1022.                 buffer[4] = 'f';
  1023.                 buffer[5] = 'i';
  1024.                 buffer[6] = 'l';
  1025.                 buffer[7] = 'e';
  1026.         }
  1027.  
  1028.         assert(i >= 0 && i < 256);
  1029.         i = clamp_tpl<int>(i, 0, 255);
  1030.         buffer[8] = 0;
  1031.         buffer[9] = 0;
  1032.         buffer[10] = 0;
  1033.         itoa(i, &(buffer[8]), 10);
  1034.  
  1035.         return buffer;
  1036. }
  1037.  
  1038. //------------------------------------------------------------------------
  1039. void CGameObject::GameSerialize(TSerialize ser)
  1040. {
  1041.         FullSerialize(ser);
  1042. }
  1043.  
  1044. struct SExtensionSerInfo
  1045. {
  1046.         uint32      extensionLocalIndex;
  1047.         uint32      priority;
  1048.         static bool SortingComparison(const SExtensionSerInfo& s0, const SExtensionSerInfo& s1)
  1049.         {
  1050.                 return s0.priority < s1.priority;
  1051.         }
  1052. };
  1053.  
  1054. void CGameObject::FullSerialize(TSerialize ser)
  1055. {
  1056.         CRY_ASSERT(ser.GetSerializationTarget() != eST_Network);
  1057.  
  1058.         if (ser.BeginOptionalGroup("GameObject", true))
  1059.         {
  1060.                 int updateState = eUS_INVALID;
  1061.                 if (ser.IsWriting())
  1062.                         updateState = (int) m_updateState;
  1063.                 ser.Value("updateState", updateState);
  1064.                 if (ser.IsReading())
  1065.                         m_updateState = (EUpdateState) updateState;
  1066.  
  1067.                 const uint8 profileDefault = 255;
  1068.                 CryFixedStringT<32> name;
  1069.                 IGameObjectSystem* pGameObjectSystem = m_pGOS;
  1070.                 std::vector<CryFixedStringT<32>> activatedExtensions;
  1071.  
  1072.                 int extensionsCount = 0;
  1073.                 if (ser.IsWriting())
  1074.                 {
  1075.                         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1076.                         {
  1077.                                 if (iter->activated)
  1078.                                 {
  1079.                                         activatedExtensions.push_back(pGameObjectSystem->GetName(iter->id));
  1080.                                 }
  1081.                         }
  1082.                         if (!activatedExtensions.empty())
  1083.                         {
  1084.                                 ser.Value("activatedExtensions", activatedExtensions);
  1085.                         }
  1086.  
  1087.                         extensionsCount = m_extensions.size();
  1088.                         ser.Value("numExtensions", extensionsCount);
  1089.  
  1090.                         if (extensionsCount > 1) // when we have many extensions, sort by serialization priority
  1091.                         {
  1092.                                 typedef std::vector<SExtensionSerInfo> TSortingList;
  1093.                                 TSortingList sortingExtensionsList;
  1094.  
  1095.                                 sortingExtensionsList.resize(m_extensions.size());
  1096.                                 {
  1097.                                         TExtensions::iterator iterS = m_extensions.begin();
  1098.                                         TSortingList::iterator iterD = sortingExtensionsList.begin();
  1099.                                         for (uint32 i = 0; iterS != m_extensions.end(); ++iterS, ++iterD, ++i)
  1100.                                         {
  1101.                                                 iterD->extensionLocalIndex = i;
  1102.                                                 iterD->priority = pGameObjectSystem->GetExtensionSerializationPriority(iterS->id);
  1103.                                         }
  1104.                                         std::sort(sortingExtensionsList.begin(), sortingExtensionsList.end(), &SExtensionSerInfo::SortingComparison);
  1105.                                 }
  1106.  
  1107.                                 // we do this to make sure that the extensions will be in the same update order after reading from savegame. We dont want to change the update order for now, to avoid possible bugs.
  1108.                                 ser.BeginGroup("UpdateOrder");
  1109.                                 for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1110.                                 {
  1111.                                         ser.BeginGroup("Extension");
  1112.                                         name = pGameObjectSystem->GetName(iter->id);
  1113.                                         ser.Value("name", name);
  1114.                                         ser.EndGroup();
  1115.                                 }
  1116.                                 ser.EndGroup();
  1117.  
  1118.                                 // actual serialization call
  1119.                                 for (TSortingList::iterator iter = sortingExtensionsList.begin(); iter != sortingExtensionsList.end(); ++iter)
  1120.                                 {
  1121.                                         SExtension& extension = m_extensions[iter->extensionLocalIndex];
  1122.                                         ser.BeginGroup("Extension");
  1123.                                         name = pGameObjectSystem->GetName(extension.id);
  1124.                                         ser.Value("name", name);
  1125.                                         extension.pExtension->FullSerialize(ser);
  1126.                                         ser.EndGroup();
  1127.                                 }
  1128.                         }
  1129.                         else
  1130.                         {
  1131.                                 if (extensionsCount == 1)
  1132.                                 {
  1133.                                         ser.BeginGroup("Extension");
  1134.                                         name = pGameObjectSystem->GetName(m_extensions[0].id);
  1135.                                         ser.Value("name", name);
  1136.                                         m_extensions[0].pExtension->FullSerialize(ser);
  1137.                                         ser.EndGroup();
  1138.                                 }
  1139.                         }
  1140.  
  1141.                         uint8 profile = profileDefault;
  1142.                         if (m_pProfileManager)
  1143.                         {
  1144.                                 for (NetworkAspectID i = 0; i < NUM_ASPECTS; i++)
  1145.                                 {
  1146.                                         NetworkAspectType aspect = 1 << i;
  1147.                                         profile = GetAspectProfile((EEntityAspects)aspect);
  1148.  
  1149.                                         ser.ValueWithDefault(AspectProfileSerializationName(i), profile, profileDefault);
  1150.                                 }
  1151.                         }
  1152.                 }
  1153.                 else //reading
  1154.                 {
  1155.                         //                      FlushExtensions(false);
  1156.                         ser.Value("activatedExtensions", activatedExtensions);
  1157.                         for (std::vector<CryFixedStringT<32>>::iterator iter = activatedExtensions.begin(); iter != activatedExtensions.end(); ++iter)
  1158.                                 ChangeExtension(iter->c_str(), eCE_Activate);
  1159.  
  1160.                         ser.Value("numExtensions", extensionsCount);
  1161.  
  1162.                         // we acquire them in the original order before the actual serialization to make sure that the update order will be the same than before saving
  1163.                         if (extensionsCount > 1)
  1164.                         {
  1165.                                 uint32 tempCount = extensionsCount;
  1166.                                 ser.BeginGroup("UpdateOrder");
  1167.                                 while (tempCount--)
  1168.                                 {
  1169.                                         ser.BeginGroup("Extension");
  1170.                                         ser.Value("name", name);
  1171.                                         AcquireExtension(name.c_str());
  1172.                                         ReleaseExtension(name.c_str());
  1173.                                         ser.EndGroup();
  1174.                                 }
  1175.                                 ser.EndGroup();
  1176.                         }
  1177.  
  1178.                         while (extensionsCount--)
  1179.                         {
  1180.                                 ser.BeginGroup("Extension");
  1181.                                 ser.Value("name", name);
  1182.                                 IGameObjectExtension* pExt = AcquireExtension(name.c_str());
  1183.                                 if (pExt)
  1184.                                 {
  1185.                                         pExt->FullSerialize(ser);
  1186.                                         ReleaseExtension(name.c_str());
  1187.                                 }
  1188.                                 ser.EndGroup();
  1189.                         }
  1190.  
  1191.                         //physicalize after serialization with the correct parameters
  1192.                         if (m_pProfileManager)
  1193.                         {
  1194.                                 for (NetworkAspectID i = 0; i < NUM_ASPECTS; i++)
  1195.                                 {
  1196.                                         NetworkAspectType aspect = 1 << i;
  1197.  
  1198.                                         uint8 profile = 0;
  1199.                                         ser.ValueWithDefault(AspectProfileSerializationName(i), profile, profileDefault);
  1200.                                         SetAspectProfile((EEntityAspects)aspect, profile, false);
  1201.                                 }
  1202.                         }
  1203.  
  1204.                 }
  1205.  
  1206.                 ser.EndGroup(); //GameObject
  1207.         }
  1208. }
  1209.  
  1210. //------------------------------------------------------------------------
  1211. bool CGameObject::NetSerialize(TSerialize ser, EEntityAspects aspect, uint8 profile, int flags)
  1212. {
  1213.         for (TExtensions::iterator it = m_extensions.begin(); it != m_extensions.end(); ++it)
  1214.                 if (!it->pExtension->NetSerialize(ser, aspect, profile, flags))
  1215.                         return false;
  1216.  
  1217.         if (aspect == eEA_Physics && !m_pProfileManager)
  1218.         {
  1219.                 GetEntity()->PhysicsNetSerialize(ser);
  1220.         }
  1221.  
  1222.         return true;
  1223. }
  1224.  
  1225. NetworkAspectType CGameObject::GetNetSerializeAspects()
  1226. {
  1227.         NetworkAspectType aspects = 0;
  1228.  
  1229.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1230.         {
  1231.                 aspects |= iter->pExtension->GetNetSerializeAspects();
  1232.         }
  1233.  
  1234.         if (!m_bNoSyncPhysics && (GetEntity()->GetPhysicalEntity() || m_pProfileManager))
  1235.         {
  1236.                 aspects |= eEA_Physics;
  1237.         }
  1238.  
  1239.         if (GetEntity()->GetProxy(ENTITY_PROXY_SCRIPT))
  1240.         {
  1241.                 aspects |= eEA_Script;
  1242.         }
  1243.  
  1244.         return aspects;
  1245. }
  1246.  
  1247. //------------------------------------------------------------------------
  1248. void CGameObject::PostSerialize()
  1249. {
  1250.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1251.         {
  1252.                 if (iter->pExtension)
  1253.                         iter->pExtension->PostSerialize();
  1254.         }
  1255.         m_distanceChecker.Reset();
  1256.  
  1257.         if (m_updateState == eUS_NotVisible_FarAway)
  1258.         {
  1259.                 GetEntity()->SetFlags(GetEntity()->GetFlags() | ENTITY_FLAG_SEND_RENDER_EVENT);
  1260.         }
  1261. }
  1262.  
  1263. //------------------------------------------------------------------------
  1264. void CGameObject::SetAuthority(bool auth)
  1265. {
  1266.         {
  1267.                 AUTO_LOCK(g_updateSchedulingProfileCritSec);
  1268.                 g_updateSchedulingProfile.insert(this);
  1269.         }
  1270.  
  1271.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1272.                 iter->pExtension->SetAuthority(auth);
  1273. }
  1274.  
  1275. //------------------------------------------------------------------------
  1276. void CGameObject::InitClient(int channelId)
  1277. {
  1278.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1279.                 iter->pExtension->InitClient(channelId);
  1280. }
  1281.  
  1282. //------------------------------------------------------------------------
  1283. void CGameObject::PostInitClient(int channelId)
  1284. {
  1285.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1286.                 iter->pExtension->PostInitClient(channelId);
  1287. }
  1288.  
  1289. //------------------------------------------------------------------------
  1290. void CGameObject::ChangedNetworkState(NetworkAspectType aspects)
  1291. {
  1292.         CGameContext* pGameContext = CCryAction::GetCryAction()->GetGameContext();
  1293.         if (!pGameContext)
  1294.                 return;
  1295.         INetContext* pNetContext = pGameContext->GetNetContext();
  1296.         if (!pNetContext)
  1297.                 return;
  1298.         IEntity* pEntity = GetEntity();
  1299.         if (!pEntity)
  1300.                 return;
  1301.         pNetContext->ChangedAspects(pEntity->GetId(), aspects);
  1302. }
  1303.  
  1304. //------------------------------------------------------------------------
  1305. void CGameObject::EnableAspect(NetworkAspectType aspects, bool enable)
  1306. {
  1307.         CGameContext* pGameContext = CCryAction::GetCryAction()->GetGameContext();
  1308.         if (!pGameContext)
  1309.                 return;
  1310.  
  1311.         if (enable)
  1312.                 m_enabledAspects |= aspects;
  1313.         else
  1314.                 m_enabledAspects &= ~aspects;
  1315.  
  1316.         pGameContext->EnableAspects(GetEntityId(), aspects, enable);
  1317. }
  1318.  
  1319. //------------------------------------------------------------------------
  1320. void CGameObject::EnableDelegatableAspect(NetworkAspectType aspects, bool enable)
  1321. {
  1322.         if (enable)
  1323.         {
  1324.                 m_delegatableAspects |= aspects;
  1325.         }
  1326.         else
  1327.         {
  1328.                 m_delegatableAspects &= ~aspects;
  1329.         }
  1330. }
  1331.  
  1332. //------------------------------------------------------------------------
  1333. template<class T>
  1334. ILINE bool CGameObject::DoGetSetExtensionParams(const char* extension, SmartScriptTable params)
  1335. {
  1336.         IGameObjectSystem* pGameObjectSystem = m_pGOS;
  1337.         SExtension ext;
  1338.         ext.id = pGameObjectSystem->GetID(extension);
  1339.         if (ext.id != IGameObjectSystem::InvalidExtensionID)
  1340.         {
  1341.                 TExtensions::iterator iter = std::lower_bound(m_extensions.begin(), m_extensions.end(), ext);
  1342.  
  1343.                 if (iter != m_extensions.end() && ext.id == iter->id)
  1344.                 {
  1345.                         T impl(params);
  1346.                         CSimpleSerialize<T> ser(impl);
  1347.                         iter->pExtension->FullSerialize(TSerialize(&ser));
  1348.                         return ser.Ok();
  1349.                 }
  1350.         }
  1351.         return false;
  1352. }
  1353.  
  1354. IGameObjectExtension* CGameObject::QueryExtension(const char* extension) const
  1355. {
  1356.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  1357.         return QueryExtension(m_pGOS->GetID(extension));
  1358. }
  1359.  
  1360. IGameObjectExtension* CGameObject::QueryExtension(IGameObjectSystem::ExtensionID id) const
  1361. {
  1362.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  1363.  
  1364.         SExtension ext;
  1365.         ext.id = id;
  1366.         if (m_pEntity && (ext.id != IGameObjectSystem::InvalidExtensionID))
  1367.         {
  1368.                 // locate the extension
  1369.                 TExtensions::const_iterator iter = std::lower_bound(m_extensions.begin(), m_extensions.end(), ext);
  1370.                 if (iter != m_extensions.end() && iter->id == ext.id)
  1371.                         return iter->pExtension;
  1372.         }
  1373.  
  1374.         return 0;
  1375. }
  1376.  
  1377. bool CGameObject::GetExtensionParams(const char* extension, SmartScriptTable params)
  1378. {
  1379.         return DoGetSetExtensionParams<CSerializeScriptTableWriterImpl>(extension, params);
  1380. }
  1381.  
  1382. bool CGameObject::SetExtensionParams(const char* extension, SmartScriptTable params)
  1383. {
  1384.         return DoGetSetExtensionParams<CSerializeScriptTableReaderImpl>(extension, params);
  1385. }
  1386.  
  1387. //------------------------------------------------------------------------
  1388. IGameObjectExtension* CGameObject::ChangeExtension(const char* name, EChangeExtension change, TSerialize* pSpawnSerializer)
  1389. {
  1390.         IGameObjectExtension* pRet = NULL;
  1391.  
  1392.         IGameObjectSystem* pGameObjectSystem = m_pGOS;
  1393.         SExtension ext;
  1394.         // fetch extension id
  1395.         ext.id = pGameObjectSystem->GetID(name);
  1396.  
  1397.         if (m_pEntity && m_bOnInitEventCalled) // init has been called, things are safe
  1398.         {
  1399.                 m_justExchanging = true;
  1400.                 if (ext.id != IGameObjectSystem::InvalidExtensionID)
  1401.                 {
  1402.                         // locate the extension
  1403.                         TExtensions::iterator iter = std::lower_bound(m_extensions.begin(), m_extensions.end(), ext);
  1404.  
  1405.                         // we're adding an extension
  1406.                         if (change == eCE_Activate || change == eCE_Acquire)
  1407.                         {
  1408.                                 if (iter != m_extensions.end() && iter->id == ext.id)
  1409.                                 {
  1410.                                         iter->refCount += (change == eCE_Acquire);
  1411.                                         iter->activated |= (change == eCE_Activate);
  1412.                                         pRet = iter->pExtension;
  1413.                                 }
  1414.                                 else
  1415.                                 {
  1416.                                         ext.refCount += (change == eCE_Acquire);
  1417.                                         ext.activated |= (change == eCE_Activate);
  1418.                                         ext.pExtension = pGameObjectSystem->Instantiate(ext.id, this, pSpawnSerializer);
  1419.                                         assert(ext.pExtension);
  1420.                                         if (ext.pExtension)
  1421.                                         {
  1422.                                                 pRet = ext.pExtension;
  1423.                                                 if (updatingEntity == GetEntityId())
  1424.                                                 {
  1425.                                                         CRY_ASSERT(m_nAddingExtension < MAX_ADDING_EXTENSIONS);
  1426.                                                         PREFAST_ASSUME(m_nAddingExtension < MAX_ADDING_EXTENSIONS);
  1427.                                                         if (m_nAddingExtension == MAX_ADDING_EXTENSIONS)
  1428.                                                                 CryFatalError("Too many extensions added in a single frame");
  1429.                                                         m_addingExtensions[m_nAddingExtension++] = ext;
  1430.                                                 }
  1431.                                                 else
  1432.                                                 {
  1433.                                                         ClearCache();
  1434.                                                         m_extensions.push_back(ext);
  1435.                                                         std::sort(m_extensions.begin(), m_extensions.end());
  1436.                                                         ext.pExtension->PostInit(this);
  1437.                                                 }
  1438.                                         }
  1439.                                 }
  1440.                         }
  1441.                         else // change == eCE_Deactivate || change == eCE_Release
  1442.                         {
  1443.  
  1444.                                 if (iter == m_extensions.end() || iter->id != ext.id)
  1445.                                 {
  1446.                                         if (change == eCE_Release)
  1447.                                         {
  1448.                                                 CRY_ASSERT(0);
  1449.                                                 CryFatalError("Attempt to release a non-existant extension %s", name);
  1450.                                         }
  1451.                                 }
  1452.                                 else
  1453.                                 {
  1454.                                         iter->refCount -= (change == eCE_Release);
  1455.                                         if (change == eCE_Deactivate)
  1456.                                                 iter->activated = false;
  1457.  
  1458.                                         if (!iter->refCount && !iter->activated && !iter->sticky)
  1459.                                         {
  1460.                                                 if (updatingEntity == GetEntityId() && numRemovingExtensions != NOT_IN_UPDATE_MODE)
  1461.                                                 {
  1462.                                                         if (numRemovingExtensions == MAX_REMOVING_EXTENSIONS)
  1463.                                                                 CryFatalError("Trying to removing too many game object extensions in one frame");
  1464.                                                         PREFAST_ASSUME(numRemovingExtensions < MAX_REMOVING_EXTENSIONS);
  1465.                                                         removingExtensions[numRemovingExtensions++] = iter->id;
  1466.                                                 }
  1467.                                                 else
  1468.                                                         RemoveExtension(iter);
  1469.                                         }
  1470.                                 }
  1471.                         }
  1472.                 }
  1473.                 m_justExchanging = false;
  1474.         }
  1475.         else if (ext.id != IGameObjectSystem::InvalidExtensionID && change == eCE_Activate) // init has not been called... we simply make a temporary extensions array, and fill in the details later
  1476.         {
  1477.                 ClearCache();
  1478.                 m_extensions.push_back(ext);
  1479.                 std::sort(m_extensions.begin(), m_extensions.end());
  1480.                 // Only activation is safe at this stage, but we need to return something to let the caller know that activation succeeded.
  1481.                 // Since this invariably means a non-NULL pointer, we return a obvious placeholder value, just in case someone tries to dereference it anyway.
  1482.                 pRet = (IGameObjectExtension*)(intptr_t)0xf0f0f0f0;
  1483.         }
  1484.  
  1485.         return pRet;
  1486. }
  1487.  
  1488. void CGameObject::RemoveExtension(const TExtensions::iterator& iter)
  1489. {
  1490.         ClearCache();
  1491.         if (iter->postUpdate)
  1492.                 DisablePostUpdates(iter->pExtension);
  1493.         IGameObjectExtension* pExtension = iter->pExtension;
  1494.         pExtension->OnShutDown();
  1495.         std::swap(m_extensions.back(), *iter);
  1496.         m_extensions.pop_back();
  1497.         std::sort(m_extensions.begin(), m_extensions.end());
  1498.         GetEntity()->RemoveComponent(pExtension);
  1499. }
  1500.  
  1501. //------------------------------------------------------------------------
  1502. void CGameObject::FlushExtensions(bool includeStickyBits)
  1503. {
  1504.         ClearCache();
  1505.         static bool inFlush = false;
  1506.  
  1507.         std::vector<IGameObjectSystem::ExtensionID> activatedExtensions_recurse;
  1508.         std::vector<IGameObjectSystem::ExtensionID>* pActivatedExtensions;
  1509.  
  1510.         bool wasInFlush = inFlush;
  1511.         if (inFlush)
  1512.         {
  1513.                 pActivatedExtensions = &activatedExtensions_recurse;
  1514.         }
  1515.         else
  1516.         {
  1517.                 pActivatedExtensions = m_pGOS->GetActivatedExtensionsTop();
  1518.                 inFlush = true;
  1519.         }
  1520.  
  1521.         CRY_ASSERT(pActivatedExtensions->empty());
  1522.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1523.         {
  1524.                 if (includeStickyBits && iter->sticky)
  1525.                 {
  1526.                         iter->sticky = false;
  1527.                         iter->activated = true;
  1528.                 }
  1529.                 if (iter->activated)
  1530.                         pActivatedExtensions->push_back(iter->id);
  1531.         }
  1532.         while (!pActivatedExtensions->empty())
  1533.         {
  1534.                 ChangeExtension(m_pGOS->GetName(pActivatedExtensions->back()), eCE_Deactivate);
  1535.                 pActivatedExtensions->pop_back();
  1536.         }
  1537.         if (includeStickyBits)
  1538.         {
  1539.                 //CRY_ASSERT( m_extensions.empty() );
  1540.  
  1541.                 // [10/12/2009 evgeny] The only way to ensure that "0 == m_pProfileManager" in all cases
  1542.                 // is to release the profile manager here explicitly.
  1543.                 // It's basically just zeroing the pointer, so not memory leak is expected.
  1544.                 ReleaseProfileManager(m_pProfileManager);
  1545.                 CRY_ASSERT(0 == m_pProfileManager);
  1546.  
  1547.                 //CRY_ASSERT(0 == m_pActionDelegate);
  1548.                 //CRY_ASSERT(0 == m_pViewDelegate);
  1549.         }
  1550.  
  1551.         inFlush = wasInFlush;
  1552. }
  1553.  
  1554. uint8 CGameObject::GetUpdateSlotEnables(IGameObjectExtension* pExtension, int slot)
  1555. {
  1556.         SExtension* pExt = GetExtensionInfo(pExtension);
  1557.         if (pExt)
  1558.         {
  1559.                 return pExt->updateEnables[slot];
  1560.         }
  1561.         return 0;
  1562. }
  1563.  
  1564. void CGameObject::EnableUpdateSlot(IGameObjectExtension* pExtension, int slot)
  1565. {
  1566.         SExtension* pExt = GetExtensionInfo(pExtension);
  1567.         if (pExt)
  1568.         {
  1569.                 CRY_ASSERT_TRACE(255 != pExt->updateEnables[slot], ("Already got 255 reasons for slot %d of '%s' to be enabled", slot, GetEntity()->GetEntityTextDescription().c_str()));
  1570.                 ++pExt->updateEnables[slot];
  1571.         }
  1572.         EvaluateUpdateActivation();
  1573. }
  1574.  
  1575. void CGameObject::DisableUpdateSlot(IGameObjectExtension* pExtension, int slot)
  1576. {
  1577.         SExtension* pExt = GetExtensionInfo(pExtension);
  1578.         if (pExt)
  1579.         {
  1580.                 if (pExt->updateEnables[slot])
  1581.                         --pExt->updateEnables[slot];
  1582.         }
  1583.         EvaluateUpdateActivation();
  1584. }
  1585.  
  1586. void CGameObject::EnablePostUpdates(IGameObjectExtension* pExtension)
  1587. {
  1588.         SExtension* pExt = GetExtensionInfo(pExtension);
  1589.         if (pExt)
  1590.         {
  1591.                 pExt->postUpdate = true;
  1592.                 m_pGOS->SetPostUpdate(this, true);
  1593.         }
  1594. }
  1595.  
  1596. void CGameObject::DisablePostUpdates(IGameObjectExtension* pExtension)
  1597. {
  1598.         bool hasPostUpdates = false;
  1599.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1600.         {
  1601.                 if (iter->pExtension == pExtension)
  1602.                 {
  1603.                         iter->postUpdate = false;
  1604.                 }
  1605.                 hasPostUpdates |= iter->postUpdate;
  1606.         }
  1607.         m_pGOS->SetPostUpdate(this, hasPostUpdates);
  1608. }
  1609.  
  1610. void CGameObject::HandleEvent(const SGameObjectEvent& evt)
  1611. {
  1612.         switch (evt.event)
  1613.         {
  1614.         case eGFE_EnablePhysics:
  1615.                 break;
  1616.         case eGFE_DisablePhysics:
  1617.                 {
  1618.                         if (IPhysicalEntity* pEnt = GetEntity()->GetPhysics())
  1619.                         {
  1620.                                 pe_action_awake awake;
  1621.                                 awake.bAwake = false;
  1622.                                 pEnt->Action(&awake);
  1623.                         }
  1624.                 }
  1625.                 break;
  1626.         }
  1627. }
  1628.  
  1629. //------------------------------------------------------------------------
  1630. void CGameObject::SendEvent(const SGameObjectEvent& event)
  1631. {
  1632.         if (event.flags & eGOEF_ToGameObject)
  1633.                 CGameObject::HandleEvent(event);
  1634.         if (event.flags & eGOEF_ToScriptSystem)
  1635.         {
  1636.                 SmartScriptTable scriptTable = GetEntity()->GetScriptTable();
  1637.                 if (event.event != IGameObjectSystem::InvalidEventID)
  1638.                 {
  1639.                         const char* eventName = m_pGOS->GetEventName(event.event);
  1640.                         if (!!scriptTable && eventName && scriptTable->HaveValue(eventName))
  1641.                         {
  1642.                                 Script::CallMethod(scriptTable, eventName);
  1643.                         }
  1644.                 }
  1645.         }
  1646.         if (event.flags & eGOEF_ToExtensions)
  1647.         {
  1648.                 if (event.target == IGameObjectSystem::InvalidExtensionID)
  1649.                 {
  1650.                         if (CCryActionCVars::Get().g_handleEvents == 1)
  1651.                         {
  1652.                                 const uint64 eventBit = 1ULL << (event.event);
  1653.                                 for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1654.                                 {
  1655.                                         const bool bHandleEvent = ((iter->eventReg & eventBit) != 0);
  1656.                                         if (bHandleEvent)
  1657.                                         {
  1658.                                                 iter->pExtension->HandleEvent(event);
  1659.                                         }
  1660.                                 }
  1661.                         }
  1662.                         else
  1663.                         {
  1664.                                 for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1665.                                 {
  1666.                                         iter->pExtension->HandleEvent(event);
  1667.                                 }
  1668.                         }
  1669.                 }
  1670.                 else
  1671.                 {
  1672.                         SExtension ext;
  1673.                         ext.id = event.target;
  1674.                         TExtensions::iterator iter = std::lower_bound(m_extensions.begin(), m_extensions.end(), ext);
  1675.                         if (iter != m_extensions.end())
  1676.                                 iter->pExtension->HandleEvent(event);
  1677.                 }
  1678.         }
  1679. }
  1680.  
  1681. void CGameObject::SetChannelId(uint16 id)
  1682. {
  1683.         m_channelId = id;
  1684.  
  1685.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1686.         {
  1687.                 if (iter->pExtension)
  1688.                         iter->pExtension->SetChannelId(id);
  1689.         }
  1690. }
  1691.  
  1692. INetChannel* CGameObject::GetNetChannel() const
  1693. {
  1694.         CGameServerNub* pServerNub = CCryAction::GetCryAction()->GetGameServerNub();
  1695.         if (pServerNub)
  1696.         {
  1697.                 CGameServerChannel* pChannel = pServerNub->GetChannel(m_channelId);
  1698.                 if (pChannel)
  1699.                         return pChannel->GetNetChannel();
  1700.         }
  1701.  
  1702.         return 0;
  1703. }
  1704.  
  1705. void CGameObject::DoInvokeRMI(_smart_ptr<CRMIBody> pBody, unsigned where, int channel)
  1706. {
  1707.         // 'where' flag validation
  1708.         if (where & eRMI_ToClientChannel)
  1709.         {
  1710.                 if (channel <= 0)
  1711.                 {
  1712.                         GameWarning("InvokeRMI: ToClientChannel specified, but no channel specified");
  1713.                         return;
  1714.                 }
  1715.                 if (where & eRMI_ToOwnClient)
  1716.                 {
  1717.                         GameWarning("InvokeRMI: ToOwnClient and ToClientChannel specified - not supported");
  1718.                         return;
  1719.                 }
  1720.         }
  1721.         if (where & eRMI_ToOwnClient)
  1722.         {
  1723.                 if (m_channelId == 0)
  1724.                 {
  1725.                         GameWarning("InvokeRMI: ToOwnClient specified, but no own client");
  1726.                         return;
  1727.                 }
  1728.                 where &= ~eRMI_ToOwnClient;
  1729.                 where |= eRMI_ToClientChannel;
  1730.                 channel = m_channelId;
  1731.         }
  1732.         if (where & eRMI_ToAllClients)
  1733.         {
  1734.                 where &= ~eRMI_ToAllClients;
  1735.                 where |= eRMI_ToOtherClients;
  1736.                 channel = -1;
  1737.         }
  1738.  
  1739.         CCryAction* pFramework = CCryAction::GetCryAction();
  1740.  
  1741.         if (where & eRMI_ToServer)
  1742.         {
  1743.                 CGameClientNub* pClientNub = pFramework->GetGameClientNub();
  1744.                 bool called = false;
  1745.                 if (pClientNub)
  1746.                 {
  1747.                         CGameClientChannel* pChannel = pClientNub->GetGameClientChannel();
  1748.                         if (pChannel)
  1749.                         {
  1750.                                 INetChannel* pNetChannel = pChannel->GetNetChannel();
  1751.                                 bool isLocal = pNetChannel->IsLocal();
  1752.                                 bool send = true;
  1753.                                 if ((where & eRMI_NoLocalCalls) != 0)
  1754.                                         if (isLocal)
  1755.                                                 send = false;
  1756.                                 if ((where & eRMI_NoRemoteCalls) != 0)
  1757.                                         if (!isLocal)
  1758.                                                 send = false;
  1759.                                 if (send)
  1760.                                 {
  1761.                                         NET_PROFILE_SCOPE_RMI(GetEntity()->GetClass()->GetName(), false);
  1762.                                         NET_PROFILE_SCOPE_RMI(GetEntity()->GetName(), false);
  1763.                                         pNetChannel->DispatchRMI(&*pBody);
  1764.                                         called = true;
  1765.                                 }
  1766.                         }
  1767.                 }
  1768.                 if (!called)
  1769.                 {
  1770.                         GameWarning("InvokeRMI: RMI via client (to server) requested but we are not a client");
  1771.                 }
  1772.         }
  1773.         if (where & (eRMI_ToClientChannel | eRMI_ToOtherClients))
  1774.         {
  1775.                 CGameServerNub* pServerNub = pFramework->GetGameServerNub();
  1776.                 if (pServerNub)
  1777.                 {
  1778.                         TServerChannelMap* pChannelMap = pServerNub->GetServerChannelMap();
  1779.                         for (TServerChannelMap::iterator iter = pChannelMap->begin(); iter != pChannelMap->end(); ++iter)
  1780.                         {
  1781.                                 bool isOwn = iter->first == channel;
  1782.                                 if (isOwn && !(where & eRMI_ToClientChannel) && !IsDemoPlayback())
  1783.                                         continue;
  1784.                                 if (!isOwn && !(where & eRMI_ToOtherClients))
  1785.                                         continue;
  1786.                                 INetChannel* pNetChannel = iter->second->GetNetChannel();
  1787.                                 if (!pNetChannel)
  1788.                                         continue;
  1789.                                 bool isLocal = pNetChannel->IsLocal();
  1790.                                 if (isLocal && (where & eRMI_NoLocalCalls) != 0)
  1791.                                         continue;
  1792.                                 if (!isLocal && (where & eRMI_NoRemoteCalls) != 0)
  1793.                                         continue;
  1794.                                 NET_PROFILE_SCOPE_RMI(GetEntity()->GetClass()->GetName(), false);
  1795.                                 NET_PROFILE_SCOPE_RMI(GetEntity()->GetName(), false);
  1796.                                 pNetChannel->DispatchRMI(&*pBody);
  1797.                         }
  1798.                 }
  1799.                 else if (pFramework->GetGameContext() &&
  1800.                          gEnv->bMultiplayer)
  1801.                 {
  1802.                         GameWarning("InvokeRMI: RMI via server (to client) requested but we are not a server");
  1803.                 }
  1804.         }
  1805. }
  1806.  
  1807. void CGameObject::PostUpdate(float frameTime)
  1808. {
  1809.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  1810.         {
  1811.                 if (iter->postUpdate)
  1812.                         iter->pExtension->PostUpdate(frameTime);
  1813.         }
  1814. }
  1815.  
  1816. void CGameObject::SetUpdateSlotEnableCondition(IGameObjectExtension* pExtension, int slot, EUpdateEnableCondition condition)
  1817. {
  1818.         bool whenVisible = false;
  1819.         bool whenInRange = false;
  1820.         bool combineOr = false;
  1821.         bool disableWithAI = true;
  1822.         bool neverUpdate = false;
  1823.  
  1824.         switch (condition)
  1825.         {
  1826.         case eUEC_Never:
  1827.                 neverUpdate = true;
  1828.                 break;
  1829.         case eUEC_Always:
  1830.                 whenVisible = false;
  1831.                 whenInRange = false;
  1832.                 combineOr = false;
  1833.                 break;
  1834.         case eUEC_Visible:
  1835.                 whenVisible = true;
  1836.                 whenInRange = false;
  1837.                 combineOr = false;
  1838.                 break;
  1839.         case eUEC_VisibleIgnoreAI:
  1840.                 whenVisible = true;
  1841.                 whenInRange = false;
  1842.                 combineOr = false;
  1843.                 disableWithAI = false;
  1844.                 break;
  1845.         case eUEC_InRange:
  1846.                 whenVisible = false;
  1847.                 whenInRange = true;
  1848.                 combineOr = false;
  1849.                 break;
  1850.         case eUEC_VisibleAndInRange:
  1851.                 whenVisible = true;
  1852.                 whenInRange = true;
  1853.                 combineOr = false;
  1854.                 break;
  1855.         case eUEC_VisibleOrInRange:
  1856.                 whenVisible = true;
  1857.                 whenInRange = true;
  1858.                 combineOr = true;
  1859.                 break;
  1860.         case eUEC_VisibleOrInRangeIgnoreAI:
  1861.                 whenVisible = true;
  1862.                 whenInRange = true;
  1863.                 combineOr = true;
  1864.                 disableWithAI = false;
  1865.                 break;
  1866.         case eUEC_WithoutAI:
  1867.                 disableWithAI = false;
  1868.                 break;
  1869.         }
  1870.  
  1871.         const uint slotbit = 1 << slot;
  1872.  
  1873.         SExtension* pExt = GetExtensionInfo(pExtension);
  1874.         if (pExt)
  1875.         {
  1876.                 SET_FLAG_FOR_SLOT(pExt->flagUpdateWhenVisible, slotbit, whenVisible);
  1877.                 SET_FLAG_FOR_SLOT(pExt->flagUpdateWhenInRange, slotbit, whenInRange);
  1878.                 SET_FLAG_FOR_SLOT(pExt->flagUpdateCombineOr, slotbit, combineOr);
  1879.                 SET_FLAG_FOR_SLOT(pExt->flagDisableWithAI, slotbit, disableWithAI);
  1880.                 SET_FLAG_FOR_SLOT(pExt->flagNeverUpdate, slotbit, neverUpdate);
  1881.         }
  1882.  
  1883.         EvaluateUpdateActivation();
  1884. }
  1885.  
  1886. bool CGameObject::ShouldUpdate()
  1887. {
  1888.         // evaluate main-loop activation
  1889.         bool shouldUpdateAI(!GetEntity()->IsHidden() && (IsProbablyVisible() || !IsProbablyDistant()));
  1890.         bool shouldBeActivated = shouldUpdateAI;
  1891.         bool hasAI = NULL != GetEntity()->GetAI();
  1892.         bool checkAIDisableOnSlots = !shouldUpdateAI && hasAI;
  1893.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end() && !shouldBeActivated; ++iter)
  1894.         {
  1895.                 uint32 slotbit = 1;
  1896.                 for (int slot = 0; slot < 4 && !shouldBeActivated; slot++)
  1897.                 {
  1898.                         shouldBeActivated |= ShouldUpdateSlot(&*iter, slot, slotbit, checkAIDisableOnSlots);
  1899.                         slotbit <<= 1;
  1900.                 }
  1901.         }
  1902.         return shouldBeActivated;
  1903. }
  1904.  
  1905. void CGameObject::EvaluateUpdateActivation()
  1906. {
  1907.         // evaluate main-loop activation
  1908.         bool shouldUpdateAI = ShouldUpdateAI();
  1909.         bool shouldBeActivated = shouldUpdateAI;
  1910.         bool hasAI = NULL != GetEntity()->GetAI();
  1911.         bool checkAIDisableOnSlots = !shouldUpdateAI && hasAI;
  1912.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end() && !shouldBeActivated; ++iter)
  1913.         {
  1914.                 uint32 slotbit = 1;
  1915.                 for (uint32 slot = 0; slot < 4 && !shouldBeActivated != 0; slot++)
  1916.                 {
  1917.                         shouldBeActivated |= ShouldUpdateSlot(&*iter, slot, slotbit, checkAIDisableOnSlots);
  1918.                         slotbit <<= 1;
  1919.                 }
  1920.         }
  1921.  
  1922.         shouldBeActivated |= (m_forceUpdate > 0);
  1923.         SetActivation(shouldBeActivated);
  1924.  
  1925.         // evaluate pre-physics activation
  1926.         bool shouldActivatePrePhysics = false;
  1927.         switch (m_prePhysicsUpdateRule)
  1928.         {
  1929.         case ePPU_WhenAIActivated:
  1930.                 if (hasAI)
  1931.                         shouldActivatePrePhysics = ShouldUpdateAI();
  1932.                 else
  1933.                 case ePPU_Always: // yes this is what i intended...
  1934.                         shouldActivatePrePhysics = true;
  1935.                 break;
  1936.         case ePPU_Never:
  1937.                 break;
  1938.         default:
  1939.                 CRY_ASSERT(false);
  1940.         }
  1941.  
  1942.         if (shouldActivatePrePhysics != m_bPrePhysicsEnabled)
  1943.         {
  1944.                 m_pEntity->PrePhysicsActivate(shouldActivatePrePhysics);
  1945.                 m_bPrePhysicsEnabled = shouldActivatePrePhysics;
  1946.         }
  1947.  
  1948.         if (TestIsProbablyVisible(m_updateState))
  1949.                 SetPhysicsDisable(false);
  1950.         else
  1951.                 switch (m_physDisableMode)
  1952.                 {
  1953.                 default:
  1954.                         CRY_ASSERT(false);
  1955.                 case eADPM_Never:
  1956.                 case eADPM_WhenAIDeactivated:
  1957.                         break;
  1958.                 case eADPM_WhenInvisibleAndFarAway:
  1959.                         SetPhysicsDisable(!TestIsProbablyVisible(m_updateState) && TestIsProbablyDistant(m_updateState));
  1960.                         break;
  1961.                 }
  1962. }
  1963.  
  1964. void CGameObject::SetActivation(bool activate)
  1965. {
  1966.         bool wasActivated = m_pEntity->IsActive();
  1967.  
  1968.         if (TestIsProbablyVisible(m_updateState))
  1969.                 SetPhysicsDisable(false);
  1970.         else
  1971.                 switch (m_physDisableMode)
  1972.                 {
  1973.                 default:
  1974.                         CRY_ASSERT(false);
  1975.                 case eADPM_Never:
  1976.                         SetPhysicsDisable(false);
  1977.                 case eADPM_WhenInvisibleAndFarAway:
  1978.                         break;
  1979.                 case eADPM_WhenAIDeactivated:
  1980.                         if (wasActivated && !activate)
  1981.                                 SetPhysicsDisable(true);
  1982.                         break;
  1983.                 }
  1984.  
  1985.         if (wasActivated != activate)
  1986.         {
  1987.                 m_pEntity->Activate(activate);
  1988.  
  1989.                 if (!activate)
  1990.                 {
  1991.                         IAIObject* aiObject = m_pEntity->GetAI();
  1992.                         IAIActorProxy* proxy = aiObject ? aiObject->GetProxy() : 0;
  1993.  
  1994.                         if (proxy)
  1995.                                 proxy->NotifyAutoDeactivated();
  1996.                 }
  1997.         }
  1998.  
  1999.         if (activate)
  2000.                 SetPhysicsDisable(false);
  2001. }
  2002.  
  2003. void CGameObject::SetPhysicsDisable(bool disablePhysics)
  2004. {
  2005.         if (disablePhysics != m_bPhysicsDisabled)
  2006.         {
  2007.                 m_bPhysicsDisabled = disablePhysics;
  2008.                 //CryLogAlways("[gobj] %s physics on %s", disablePhysics? "disable" : "enable", GetEntity()->GetName());
  2009.                 SGameObjectEvent goe(disablePhysics ? eGFE_DisablePhysics : eGFE_EnablePhysics, eGOEF_ToExtensions | eGOEF_ToGameObject);
  2010.                 SendEvent(goe);
  2011.         }
  2012. }
  2013.  
  2014. /*
  2015.    void CGameObject::SetVisibility( bool isVisible )
  2016.    {
  2017.    if (isVisible != m_isVisible)
  2018.    {
  2019.    //           CryLogAlways("%s is now %svisible", m_pEntity->GetName(), isVisible? "" : "in");
  2020.  
  2021.     uint32 flags = m_pEntity->GetFlags();
  2022.     if (isVisible)
  2023.       flags &= ~ENTITY_FLAG_SEND_RENDER_EVENT;
  2024.     else
  2025.       flags |= ENTITY_FLAG_SEND_RENDER_EVENT;
  2026.     m_pEntity->SetFlags(flags);
  2027.  
  2028.     m_isVisible = isVisible;
  2029.    }
  2030.    }
  2031.  */
  2032.  
  2033. IWorldQuery* CGameObject::GetWorldQuery()
  2034. {
  2035.         if (IWorldQuery* query = (IWorldQuery*)QueryExtension("WorldQuery"))
  2036.                 return query;
  2037.         else
  2038.                 return NULL;
  2039. }
  2040.  
  2041. IMovementController* CGameObject::GetMovementController()
  2042. {
  2043.         IActor* pActor = CCryAction::GetCryAction()->GetIActorSystem()->GetActor(m_pEntity->GetId());
  2044.         if (pActor != NULL)
  2045.                 return pActor->GetMovementController();
  2046.         else if (IVehicle* pVehicle = CCryAction::GetCryAction()->GetIVehicleSystem()->GetVehicle(m_pEntity->GetId()))
  2047.                 return pVehicle->GetMovementController();
  2048.         else
  2049.                 return m_pMovementController;
  2050. }
  2051.  
  2052. uint8 CGameObject::GetAspectProfile(EEntityAspects aspect)
  2053. {
  2054.         uint8 profile = 255;
  2055.         if (m_isBoundToNetwork)
  2056.         {
  2057.                 if (CGameContext* pGC = CCryAction::GetCryAction()->GetCryAction()->GetGameContext())
  2058.                 {
  2059.                         if (INetContext* pNC = pGC->GetNetContext())
  2060.                                 profile = pNC->GetAspectProfile(GetEntityId(), aspect);
  2061.                 }
  2062.         }
  2063.         else
  2064.                 profile = m_profiles[BitIndex(NetworkAspectType(aspect))];
  2065.  
  2066.         return profile;
  2067. }
  2068.  
  2069. bool CGameObject::SetAspectProfile(EEntityAspects aspect, uint8 profile, bool fromNetwork)
  2070. {
  2071.         bool ok = DoSetAspectProfile(aspect, profile, fromNetwork);
  2072.  
  2073.         if (ok && aspect == eEA_Physics && m_isBoundToNetwork && gEnv->bMultiplayer)
  2074.         {
  2075.                 if (IPhysicalEntity* pEnt = GetEntity()->GetPhysics())
  2076.                 {
  2077.                         pe_params_flags flags;
  2078.                         flags.flagsOR = pef_log_collisions;
  2079.                         pEnt->SetParams(&flags);
  2080.                 }
  2081.         }
  2082.  
  2083.         return ok;
  2084. }
  2085.  
  2086. bool CGameObject::DoSetAspectProfile(EEntityAspects aspect, uint8 profile, bool fromNetwork)
  2087. {
  2088.         if (m_isBoundToNetwork)
  2089.         {
  2090.                 if (fromNetwork)
  2091.                 {
  2092.                         if (m_pProfileManager)
  2093.                         {
  2094.                                 if (m_pProfileManager->SetAspectProfile(aspect, profile))
  2095.                                 {
  2096.                                         m_profiles[BitIndex(NetworkAspectType(aspect))] = profile;
  2097.                                         return true;
  2098.                                 }
  2099.                         }
  2100.                         else
  2101.                                 return false;
  2102.                 }
  2103.                 else
  2104.                 {
  2105.                         if (CGameContext* pGameContext = CCryAction::GetCryAction()->GetGameContext())
  2106.                         {
  2107.                                 if (INetContext* pNetContext = pGameContext->GetNetContext())
  2108.                                 {
  2109.                                         pNetContext->SetAspectProfile(GetEntityId(), aspect, profile);
  2110.                                         m_profiles[BitIndex(NetworkAspectType(aspect))] = profile;
  2111.                                         return true;
  2112.                                 }
  2113.                         }
  2114.                         return false;
  2115.                 }
  2116.         }
  2117.         else if (m_pProfileManager)
  2118.         {
  2119.                 //CRY_ASSERT( !fromNetwork );
  2120.                 if (m_pProfileManager->SetAspectProfile(aspect, profile))
  2121.                 {
  2122.                         m_profiles[BitIndex(NetworkAspectType(aspect))] = profile;
  2123.                         return true;
  2124.                 }
  2125.         }
  2126.         return false;
  2127. }
  2128.  
  2129. void CGameObject::AttachDistanceChecker()
  2130. {
  2131.         if (CCryAction::GetCryAction()->IsEditing())
  2132.                 return;
  2133.  
  2134.         m_distanceChecker.Init(m_pGOS, GetEntityId());
  2135. }
  2136.  
  2137. void CGameObject::ForceUpdate(bool force)
  2138. {
  2139.         if (force)
  2140.                 ++m_forceUpdate;
  2141.         else
  2142.                 --m_forceUpdate;
  2143.  
  2144.         CRY_ASSERT(m_forceUpdate >= 0);
  2145. }
  2146.  
  2147. struct SContainerSer : public ISerializableInfo
  2148. {
  2149.         void SerializeWith(TSerialize ser)
  2150.         {
  2151.                 for (size_t i = 0; i < m_children.size(); i++)
  2152.                         m_children[i]->SerializeWith(ser);
  2153.         }
  2154.  
  2155.         std::vector<ISerializableInfoPtr> m_children;
  2156. };
  2157.  
  2158. ISerializableInfoPtr CGameObject::GetSpawnInfo()
  2159. {
  2160.         _smart_ptr<SContainerSer> pC;
  2161.  
  2162.         for (TExtensions::iterator iter = m_extensions.begin(); iter != m_extensions.end(); ++iter)
  2163.         {
  2164.                 if (iter->pExtension)
  2165.                 {
  2166.                         ISerializableInfoPtr pS = iter->pExtension->GetSpawnInfo();
  2167.                         if (pS)
  2168.                         {
  2169.                                 if (!pC)
  2170.                                         pC = new SContainerSer;
  2171.                                 pC->m_children.push_back(pS);
  2172.                         }
  2173.                 }
  2174.         }
  2175.         return &*pC;
  2176. }
  2177.  
  2178. void CGameObject::SetNetworkParent(EntityId id)
  2179. {
  2180.         if (!GetEntity()->IsInitialized())
  2181.         {
  2182.                 m_cachedParentId = id;
  2183.                 return;
  2184.         }
  2185.  
  2186.         CCryAction* pCryAction = CCryAction::GetCryAction();
  2187.         INetContext* pNetContext = pCryAction ? pCryAction->GetNetContext() : NULL;
  2188.  
  2189.         if (pNetContext)
  2190.         {
  2191.                 pNetContext->SetParentObject(GetEntityId(), id);
  2192.         }
  2193. }
  2194.  
  2195. uint8 CGameObject::GetDefaultProfile(EEntityAspects aspect)
  2196. {
  2197.         if (m_pProfileManager)
  2198.                 return m_pProfileManager->GetDefaultProfile(aspect);
  2199.         else
  2200.                 return 0;
  2201. }
  2202.  
  2203. bool CGameObject::SetAIActivation(EGameObjectAIActivationMode mode)
  2204. {
  2205.         // this should be done only for gameobjects with AI. Otherwise breaks weapons (scope update, etc)
  2206.         if (!GetEntity()->HasAI())
  2207.                 return false;
  2208.  
  2209.         if (m_aiMode != mode)
  2210.         {
  2211.                 m_aiMode = mode;
  2212.                 EvaluateUpdateActivation(); // need to recheck any updates on slots
  2213.         }
  2214.  
  2215.         return GetEntity()->IsActive();
  2216. }
  2217.  
  2218. bool CGameObject::ShouldUpdateAI()
  2219. {
  2220.         if (GetEntity()->IsHidden() || !GetEntity()->HasAI())
  2221.                 return false;
  2222.  
  2223.         switch (m_aiMode)
  2224.         {
  2225.         case eGOAIAM_Never:
  2226.                 return false;
  2227.         case eGOAIAM_Always:
  2228.                 return true;
  2229.         case eGOAIAM_VisibleOrInRange:
  2230.                 return IsProbablyVisible() || !IsProbablyDistant();
  2231.         default:
  2232.                 CRY_ASSERT(false);
  2233.                 return false;
  2234.         }
  2235. }
  2236.  
  2237. void CGameObject::EnablePrePhysicsUpdate(EPrePhysicsUpdate updateRule)
  2238. {
  2239.         m_prePhysicsUpdateRule = updateRule;
  2240.         EvaluateUpdateActivation();
  2241. }
  2242.  
  2243. void CGameObject::Pulse(uint32 pulse)
  2244. {
  2245.         if (CGameContext* pGC = CCryAction::GetCryAction()->GetGameContext())
  2246.                 pGC->GetNetContext()->PulseObject(GetEntityId(), pulse);
  2247. }
  2248.  
  2249. void CGameObject::PostRemoteSpawn()
  2250. {
  2251.         for (size_t i = 0; i < m_extensions.size(); ++i)
  2252.                 m_extensions[i].pExtension->PostRemoteSpawn();
  2253. }
  2254.  
  2255. void CGameObject::AcquireMutex()
  2256. {
  2257.         m_mutex.Lock();
  2258. }
  2259.  
  2260. void CGameObject::ReleaseMutex()
  2261. {
  2262.         m_mutex.Unlock();
  2263. }
  2264.  
  2265. void CGameObject::GetMemoryUsage(ICrySizer* s) const
  2266. {
  2267.         {
  2268.                 SIZER_SUBCOMPONENT_NAME(s, "GameObject");
  2269.                 s->AddObject(this, sizeof(*this));
  2270.                 s->AddObject(m_extensions);
  2271.                 for (int i = 0; i < CGameObject::MAX_ADDING_EXTENSIONS; ++i)
  2272.                         s->AddObject(m_addingExtensions[i]);
  2273.         }
  2274. }
  2275.  
  2276. void CGameObject::RegisterAsPredicted()
  2277. {
  2278.         CRY_ASSERT(!m_predictionHandle);
  2279.         m_predictionHandle = CCryAction::GetCryAction()->GetNetContext()->RegisterPredictedSpawn(CCryAction::GetCryAction()->GetClientChannel(), GetEntityId());
  2280. }
  2281.  
  2282. int CGameObject::GetPredictionHandle()
  2283. {
  2284.         return m_predictionHandle;
  2285. }
  2286.  
  2287. void CGameObject::RegisterAsValidated(IGameObject* pGO, int predictionHandle)
  2288. {
  2289.         if (!pGO)
  2290.                 return;
  2291.         m_predictionHandle = predictionHandle;
  2292.         CCryAction::GetCryAction()->GetNetContext()->RegisterValidatedPredictedSpawn(pGO->GetNetChannel(), m_predictionHandle, GetEntityId());
  2293. }
  2294.  
  2295. void CGameObject::SetAutoDisablePhysicsMode(EAutoDisablePhysicsMode mode)
  2296. {
  2297.         if (m_physDisableMode != mode)
  2298.         {
  2299.                 m_physDisableMode = mode;
  2300.                 EvaluateUpdateActivation();
  2301.         }
  2302. }
  2303.  
  2304. void CGameObject::RequestRemoteUpdate(NetworkAspectType aspectMask)
  2305. {
  2306.         if (INetContext* pNC = CCryAction::GetCryAction()->GetNetContext())
  2307.                 pNC->RequestRemoteUpdate(GetEntityId(), aspectMask);
  2308. }
  2309.  
  2310. #if GAME_OBJECT_SUPPORTS_CUSTOM_USER_DATA
  2311. void* CGameObject::GetUserData() const
  2312. {
  2313.         return m_pUserData;
  2314. }
  2315.  
  2316. void CGameObject::SetUserData(void* ptr)
  2317. {
  2318.         m_pUserData = ptr;
  2319. }
  2320. #endif
  2321.  
  2322. void CGameObject::RegisterExtForEvents(IGameObjectExtension* piExtention, const int* pEvents, const int numEvents)
  2323. {
  2324.         SExtension* pExtension = GetExtensionInfo(piExtention);
  2325.         if (pExtension)
  2326.         {
  2327.                 if (pEvents)
  2328.                 {
  2329.                         uint64 eventReg = 0;
  2330.                         for (int i = 0; i < numEvents; ++i)
  2331.                         {
  2332.                                 const int event = pEvents[i];
  2333.                                 eventReg |= 1ULL << (event);
  2334.                         }
  2335.                         pExtension->eventReg |= eventReg;
  2336.                 }
  2337.                 else
  2338.                 {
  2339.                         pExtension->eventReg = ~0;
  2340.                 }
  2341.         }
  2342. }
  2343.  
  2344. void CGameObject::UnRegisterExtForEvents(IGameObjectExtension* piExtention, const int* pEvents, const int numEvents)
  2345. {
  2346.         SExtension* pExtension = GetExtensionInfo(piExtention);
  2347.         if (pExtension)
  2348.         {
  2349.                 if (pEvents)
  2350.                 {
  2351.                         uint64 eventReg = 0;
  2352.                         for (int i = 0; i < numEvents; ++i)
  2353.                         {
  2354.                                 const int event = pEvents[i];
  2355.                                 eventReg |= 1ULL << (event);
  2356.                         }
  2357.                         pExtension->eventReg &= ~eventReg;
  2358.                 }
  2359.                 else
  2360.                 {
  2361.                         pExtension->eventReg = 0;
  2362.                 }
  2363.         }
  2364. }
  2365.  
  2366. //////////////////////////////////////////////////////////////////////////
  2367. //////////////////////////////////////////////////////////////////////////
  2368. #if 0
  2369. // deprecated and won't compile at all...
  2370. void SDistanceChecker::Init(CGameObjectSystem* pGameObjectSystem, EntityId receiverId)
  2371. {
  2372.         IEntity* pDistanceChecker = pGameObjectSystem->CreatePlayerProximityTrigger();
  2373.         if (pDistanceChecker)
  2374.         {
  2375.                 ((IEntityTriggerComponent*)pDistanceChecker->GetProxy(ENTITY_PROXY_TRIGGER))->ForwardEventsTo(receiverId);
  2376.                 m_distanceCheckerTimer = -1.0f;
  2377.                 m_distanceChecker = pDistanceChecker->GetId();
  2378.                 Update(0.0f);
  2379.         }
  2380. }
  2381.  
  2382. void SDistanceChecker::Reset()
  2383. {
  2384.         if (m_distanceChecker)
  2385.         {
  2386.                 gEnv->pEntitySystem->RemoveEntity(m_distanceChecker);
  2387.                 m_distanceChecker = 0;
  2388.         }
  2389.         m_distanceChecker = 0.0f;
  2390. }
  2391.  
  2392. void SDistanceChecker::Update(CGameObject& owner, float frameTime)
  2393. {
  2394.         if (!m_distanceChecker)
  2395.                 return;
  2396.  
  2397.         bool ok = false;
  2398.         IEntity* pDistanceChecker = gEnv->pEntitySystem->GetEntity(m_distanceChecker);
  2399.         if (pDistanceChecker)
  2400.         {
  2401.                 m_distanceCheckerTimer -= frameTime;
  2402.                 if (m_distanceCheckerTimer < 0.0f)
  2403.                 {
  2404.                         IEntityTriggerComponent* pProxy = (IEntityTriggerComponent*)pDistanceChecker->GetProxy(ENTITY_PROXY_TRIGGER);
  2405.                         if (pProxy)
  2406.                         {
  2407.                                 pProxy->SetTriggerBounds(CreateDistanceAABB(owner.GetEntity()->GetWorldPos()));
  2408.                                 m_distanceCheckerTimer = DISTANCE_CHECKER_TIMEOUT;
  2409.                                 ok = true;
  2410.                         }
  2411.                 }
  2412.                 else
  2413.                 {
  2414.                         ok = true;
  2415.                 }
  2416.         }
  2417.  
  2418.         if (!ok)
  2419.         {
  2420.                 Reset();
  2421.  
  2422.                 owner.AttachDistanceChecker();
  2423.         }
  2424. }
  2425.  
  2426. #endif
  2427.  
downloadGameObject.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