BVB Source Codes

CRYENGINE Show Interactor.cpp Source code

Return Download CRYENGINE: download Interactor.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "Interactor.h"
  5. #include "CryAction.h"
  6. #include "IGameRulesSystem.h"
  7. #include "WorldQuery.h"
  8. #include "IActorSystem.h"
  9. #include "CryActionCVars.h"
  10.  
  11. CInteractor::CInteractor()
  12. {
  13.         m_pQuery = 0;
  14.         m_pGameRules = 0;
  15.  
  16.         m_nextOverId = m_overId = 0;
  17.         m_nextOverIdx = m_overIdx = -100;
  18.         m_nextOverTime = m_overTime = 0.0f;
  19.         m_sentLongHover = m_sentMessageHover = false;
  20.  
  21.         m_funcIsUsable = m_funcAreUsable = m_funcOnNewUsable = m_funcOnUsableMessage = m_funcOnLongHover = 0;
  22.  
  23.         m_pTimer = gEnv->pTimer;
  24.         m_pEntitySystem = gEnv->pEntitySystem;
  25.  
  26.         m_useHoverTime = 0.05f;
  27.         m_unUseHoverTime = 0.2f;
  28.         m_messageHoverTime = 0.05f;
  29.         m_longHoverTime = 5.0f;
  30.  
  31.         m_lockedByEntityId = m_lockEntityId = 0;
  32.         m_lockIdx = 0;
  33.  
  34.         m_lastRadius = 2.0f;
  35.  
  36. }
  37.  
  38. bool CInteractor::Init(IGameObject* pGameObject)
  39. {
  40.         SetGameObject(pGameObject);
  41.         if (!m_pQuery)
  42.         {
  43.                 m_pQuery = (CWorldQuery*) GetGameObject()->AcquireExtension("WorldQuery");
  44.                 if (!m_pQuery)
  45.                         return false;
  46.         }
  47.  
  48.         m_pQuery->SetProximityRadius(CCryActionCVars::Get().playerInteractorRadius);
  49.  
  50.         m_pGameRules = CCryAction::GetCryAction()->GetIGameRulesSystem()->GetCurrentGameRulesEntity()->GetScriptTable();
  51.         m_pGameRules->GetValue("IsUsable", m_funcIsUsable);
  52.         m_pGameRules->GetValue("AreUsable", m_funcAreUsable);
  53.         m_pGameRules->GetValue("OnNewUsable", m_funcOnNewUsable);
  54.         m_pGameRules->GetValue("OnUsableMessage", m_funcOnUsableMessage);
  55.         m_pGameRules->GetValue("OnLongHover", m_funcOnLongHover);
  56.  
  57.         m_areUsableEntityList.Create(gEnv->pScriptSystem);
  58.  
  59.         //Should be more than enough for average situation
  60.         m_frameQueryVector.reserve(16);
  61.  
  62.         m_queryMethods = (m_funcAreUsable) ? "m" : "rb";  //m is optimized for Crysis2, "rb" is Crysis1 compatible
  63.  
  64.         return true;
  65. }
  66.  
  67. void CInteractor::PostInit(IGameObject* pGameObject)
  68. {
  69.         pGameObject->EnableUpdateSlot(this, 0);
  70. }
  71.  
  72. bool CInteractor::ReloadExtension(IGameObject* pGameObject, const SEntitySpawnParams& params)
  73. {
  74.         ResetGameObject();
  75.  
  76.         CRY_ASSERT_MESSAGE(false, "CInteractor::ReloadExtension not implemented");
  77.  
  78.         return false;
  79. }
  80.  
  81. CInteractor::~CInteractor()
  82. {
  83.         if (m_pQuery)
  84.                 GetGameObject()->ReleaseExtension("WorldQuery");
  85.         gEnv->pScriptSystem->ReleaseFunc(m_funcIsUsable);
  86.         gEnv->pScriptSystem->ReleaseFunc(m_funcAreUsable);
  87.         gEnv->pScriptSystem->ReleaseFunc(m_funcOnNewUsable);
  88.         gEnv->pScriptSystem->ReleaseFunc(m_funcOnUsableMessage);
  89.         gEnv->pScriptSystem->ReleaseFunc(m_funcOnLongHover);
  90. }
  91.  
  92. void CInteractor::Release()
  93. {
  94.         delete this;
  95. }
  96.  
  97. ScriptAnyValue CInteractor::EntityIdToScript(EntityId id)
  98. {
  99.         if (id)
  100.         {
  101.                 ScriptHandle hdl;
  102.                 hdl.n = id;
  103.                 return ScriptAnyValue(hdl);
  104.         }
  105.         else
  106.         {
  107.                 return ScriptAnyValue();
  108.         }
  109. }
  110.  
  111. void CInteractor::Update(SEntityUpdateContext&, int)
  112. {
  113.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  114.  
  115.         EntityId newOverId = INVALID_ENTITYID;
  116.         int usableIdx = 0;
  117.  
  118.         const EntityId myId = GetGameObject()->GetEntityId();
  119.         const IActor* const pActor = CCryAction::GetCryAction()->GetIActorSystem()->GetActor(myId);
  120.         if (pActor && !pActor->IsInteracting())
  121.         {
  122.                 if (m_lockedByEntityId)
  123.                 {
  124.                         newOverId = m_lockEntityId;
  125.                         usableIdx = m_lockIdx;
  126.                 }
  127.                 else
  128.                 {
  129.                         if ((CCryActionCVars::Get().playerInteractorRadius != m_lastRadius) && m_pQuery)
  130.                         {
  131.                                 m_lastRadius = CCryActionCVars::Get().playerInteractorRadius;
  132.                                 m_pQuery->SetProximityRadius(m_lastRadius);
  133.                         }
  134.  
  135.                         PerformQueries(newOverId, usableIdx);
  136.                 }
  137.         }
  138.         UpdateTimers(newOverId, usableIdx);
  139. }
  140.  
  141. void CInteractor::PerformQueries(EntityId& id, int& idx)
  142. {
  143.         SQueryResult bestResult;
  144.         bestResult.entityId = 0;
  145.         bestResult.slotIdx = 0;
  146.         bestResult.hitDistance = FLT_MAX;
  147.  
  148.         for (string::const_iterator iter = m_queryMethods.begin(); iter != m_queryMethods.end(); ++iter)
  149.         {
  150.                 bool found;
  151.                 SQueryResult result;
  152.                 switch (*iter)
  153.                 {
  154.                 case 'r':
  155.                         found = PerformRayCastQuery(result);
  156.                         break;
  157.                 case 'b':
  158.                         found = PerformViewCenterQuery(result);
  159.                         break;
  160.                 case 'd':
  161.                         found = PerformDotFilteredProximityQuery(result, 0.8f);
  162.                         break;
  163.                 case 'm':
  164.                         found = PerformMergedQuery(result, 0.8f);
  165.                         break;
  166.                 default:
  167.                         GameWarning("Interactor: Invalid query mode '%c'", *iter);
  168.                         found = false;
  169.                 }
  170.                 if (found && result.hitDistance < bestResult.hitDistance)
  171.                 {
  172.                         if (bestResult.entityId && !result.entityId)
  173.                                 ;
  174.                         else
  175.                                 bestResult = result;
  176.                 }
  177.         }
  178.         id = bestResult.entityId;
  179.         idx = bestResult.slotIdx;
  180. }
  181.  
  182. bool CInteractor::PerformDotFilteredProximityQuery(SQueryResult& r, float minDot)
  183. {
  184.         float minDistanceToCenterSq(999.9f);
  185.         IEntity* pNearestEntityToViewCenter(NULL);
  186.         float maxDot = -1.0f;
  187.  
  188.         Vec3 viewDirection = m_pQuery->GetDir();
  189.         viewDirection.Normalize();
  190.  
  191.         Vec3 viewPos = m_pQuery->GetPos();
  192.  
  193.         const Entities& entities = m_pQuery->ProximityQuery();
  194.         for (Entities::const_iterator i = entities.begin(); i != entities.end(); ++i)
  195.         {
  196.                 IEntity* pEntity = m_pEntitySystem->GetEntity(*i);
  197.                 if (!pEntity)
  198.                         continue;
  199.  
  200.                 AABB bbox;
  201.                 pEntity->GetWorldBounds(bbox);
  202.                 Vec3 itemPos = bbox.GetCenter();
  203.  
  204.                 Vec3 diff = itemPos - viewPos;
  205.  
  206.                 Vec3 dirToItem = diff.GetNormalized();
  207.  
  208.                 float dotToItem = dirToItem.dot(viewDirection);
  209.  
  210.                 if (dotToItem > maxDot)
  211.                 {
  212.                         maxDot = dotToItem;
  213.                         pNearestEntityToViewCenter = pEntity;
  214.                         r.hitPosition = itemPos;
  215.                         r.hitDistance = (itemPos - viewPos).GetLengthSquared();
  216.                 }
  217.         }
  218.  
  219.         if (pNearestEntityToViewCenter && maxDot > minDot)
  220.         {
  221.                 r.hitDistance = sqrt_tpl(r.hitDistance);
  222.                 PerformUsableTestAndCompleteIds(pNearestEntityToViewCenter, r);
  223.                 return true;
  224.         }
  225.         else
  226.         {
  227.                 return false;
  228.         }
  229. }
  230.  
  231. bool CInteractor::PerformRayCastQuery(SQueryResult& r)
  232. {
  233.         if (const ray_hit* pHit = m_pQuery->RaycastQuery())
  234.         {
  235.                 EntityId targetId = m_pQuery->GetLookAtEntityId();
  236.                 IEntity* pTargetEntity = m_pEntitySystem->GetEntity(targetId);
  237.                 if (pTargetEntity)
  238.                 {
  239.                         r.hitPosition = pHit->pt;
  240.                         r.hitDistance = pHit->dist;
  241.                         return PerformUsableTestAndCompleteIds(pTargetEntity, r);
  242.                 }
  243.         }
  244.         return false;
  245. }
  246.  
  247. bool CInteractor::PerformViewCenterQuery(SQueryResult& r)
  248. {
  249.  
  250.         float minDistanceToCenterSq(999.9f);
  251.         IEntity* pNearestEntityToViewCenter(NULL);
  252.  
  253.         Vec3 viewDirection = m_pQuery->GetDir();
  254.         viewDirection.Normalize();
  255.         viewDirection *= m_lastRadius;
  256.         Vec3 viewPos = m_pQuery->GetPos();
  257.  
  258.         Line viewLine(viewPos, viewDirection);
  259.  
  260.         const Entities& entities = m_pQuery->GetEntitiesInFrontOf();
  261.         for (Entities::const_iterator i = entities.begin(); i != entities.end(); ++i)
  262.         {
  263.  
  264.                 IEntity* pEntity = m_pEntitySystem->GetEntity(*i);
  265.                 if (!pEntity)
  266.                         continue;
  267.  
  268.                 AABB bbox;
  269.                 pEntity->GetWorldBounds(bbox);
  270.                 Vec3 itemPos = bbox.GetCenter();
  271.  
  272.                 float dstSqr = LinePointDistanceSqr(viewLine, itemPos);
  273.                 if ((dstSqr < minDistanceToCenterSq))
  274.                 {
  275.                         r.hitPosition = itemPos;
  276.                         r.hitDistance = (itemPos - viewPos).GetLengthSquared();
  277.                         minDistanceToCenterSq = dstSqr;
  278.                         pNearestEntityToViewCenter = pEntity;
  279.                 }
  280.  
  281.         }
  282.  
  283.         if (pNearestEntityToViewCenter && PerformUsableTestAndCompleteIds(pNearestEntityToViewCenter, r))
  284.         {
  285.                 return true;
  286.         }
  287.  
  288.         return false;
  289. }
  290.  
  291. bool CInteractor::PerformMergedQuery(SQueryResult& r, float minDot)
  292. {
  293.         //Clear before re-using it
  294.         m_frameQueryVector.clear();
  295.  
  296.         //Check if owner can interact first
  297.         IActor* pActor = CCryAction::GetCryAction()->GetIActorSystem()->GetActor(GetEntityId());
  298.         bool canUserInteract = pActor ? (!pActor->IsDead()) && (pActor->GetSpectatorMode() == 0) : false;
  299.  
  300.         if (!canUserInteract)
  301.                 return false;
  302.  
  303.         //1. - Raycast query
  304.         EntityId lookAtEntityId = 0;
  305.         if (const ray_hit* pHit = m_pQuery->RaycastQuery())
  306.         {
  307.                 if (IEntity* pTargetEntity = m_pEntitySystem->GetEntity(m_pQuery->GetLookAtEntityId()))
  308.                 {
  309.                         if (IsEntityUsable(pTargetEntity))
  310.                         {
  311.                                 SQueryResult rayCastResult;
  312.                                 rayCastResult.entityId = pTargetEntity->GetId();
  313.                                 rayCastResult.hitDistance = pHit->dist;
  314.                                 rayCastResult.hitPosition = pHit->pt;
  315.                                 m_frameQueryVector.push_back(TQueryElement(pTargetEntity, rayCastResult));
  316.  
  317.                                 lookAtEntityId = rayCastResult.entityId;
  318.                         }
  319.                 }
  320.         }
  321.  
  322.         //2. - Proximity query
  323.         SQueryResult tempQuery;
  324.         const Entities& entities = m_pQuery->ProximityQuery();
  325.         for (Entities::const_iterator entityCit = entities.begin(); entityCit != entities.end(); ++entityCit)
  326.         {
  327.                 const EntityId entityId = *entityCit;
  328.                 if (IEntity* pEntity = m_pEntitySystem->GetEntity(entityId))
  329.                 {
  330.                         if (IsEntityUsable(pEntity))
  331.                         {
  332.                                 tempQuery.entityId = entityId;
  333.                                 m_frameQueryVector.push_back(TQueryElement(pEntity, tempQuery));
  334.                         }
  335.                 }
  336.         }
  337.  
  338.         //3. - Perform usable test on all entities at once
  339.         PerformUsableTestOnEntities(m_frameQueryVector);
  340.  
  341.         //4. - Pick the best result
  342.         const int itemReturnIdx = 725725;
  343.  
  344.         float minDistanceToCenterSqr(FLT_MAX);
  345.         float bestDotResult = minDot;
  346.  
  347.         IEntity* pNearestDotEntity(NULL);
  348.         IEntity* pNearestBoxEntity(NULL);
  349.         SQueryResult bestBoxResult;
  350.  
  351.         const Vec3 viewDirection = m_pQuery->GetDir() * m_lastRadius;
  352.         const Vec3 viewDirectionNormalized = viewDirection.GetNormalized();
  353.         const Vec3 viewPos = m_pQuery->GetPos();
  354.  
  355.         for (TQueryVector::iterator queryIt = m_frameQueryVector.begin(); queryIt != m_frameQueryVector.end(); ++queryIt)
  356.         {
  357.                 IEntity* pEntity = queryIt->first;
  358.                 SQueryResult& currentElement = queryIt->second;
  359.                 if (currentElement.slotIdx)
  360.                 {
  361.                         //If it is the ray-cast one, early out here
  362.                         if (currentElement.entityId == lookAtEntityId)
  363.                         {
  364.                                 r = currentElement;
  365.                                 return true;
  366.                         }
  367.  
  368.                         AABB bbox;
  369.                         pEntity->GetWorldBounds(bbox);
  370.  
  371.                         const Vec3 entityCenterPos = !bbox.IsEmpty() ? bbox.GetCenter() : pEntity->GetWorldPos();
  372.  
  373.                         const Vec3 dirToEntity = (entityCenterPos - viewPos).GetNormalizedSafe();
  374.                         const Line viewLine(viewPos, viewDirection);
  375.                         const float linePointDistanceSqr = LinePointDistanceSqr(viewLine, entityCenterPos);
  376.  
  377.                         if (linePointDistanceSqr >= minDistanceToCenterSqr)
  378.                                 continue;
  379.  
  380.                         const float dotToEntity = viewDirectionNormalized.Dot(dirToEntity);
  381.  
  382.                         // TODO: Improve this simple way of detecting if the entity is an item
  383.                         bool isPickableItem = (currentElement.slotIdx == itemReturnIdx);
  384.  
  385.                         if (dotToEntity > bestDotResult)
  386.                         {
  387.                                 bestDotResult = dotToEntity;
  388.                                 r.entityId = currentElement.entityId;
  389.                                 r.slotIdx = currentElement.slotIdx;
  390.                                 r.hitPosition = entityCenterPos;
  391.                                 r.hitDistance = (entityCenterPos - viewPos).GetLength();
  392.                                 minDistanceToCenterSqr = linePointDistanceSqr;
  393.                                 pNearestDotEntity = pEntity;
  394.                         }
  395.                         else if (pNearestDotEntity == NULL && !bbox.IsEmpty())
  396.                         {
  397.  
  398.                                 //If fails, bbox overlap
  399.                                 const Lineseg viewLineSeg(viewPos, viewPos + viewDirection);
  400.                                 if (Overlap::Lineseg_AABB(viewLineSeg, bbox))
  401.                                 {
  402.                                         bestBoxResult.entityId = currentElement.entityId;
  403.                                         bestBoxResult.slotIdx = currentElement.slotIdx;
  404.                                         bestBoxResult.hitPosition = entityCenterPos;
  405.                                         bestBoxResult.hitDistance = (entityCenterPos - viewPos).GetLength();
  406.                                         minDistanceToCenterSqr = linePointDistanceSqr;
  407.                                         pNearestBoxEntity = pEntity;
  408.                                 }
  409.                                 else if (isPickableItem)
  410.                                 {
  411.                                         bestBoxResult.entityId = currentElement.entityId;
  412.                                         bestBoxResult.slotIdx = currentElement.slotIdx;
  413.                                         bestBoxResult.hitPosition = entityCenterPos;
  414.                                         bestBoxResult.hitDistance = (entityCenterPos - viewPos).GetLength();
  415.                                         minDistanceToCenterSqr = linePointDistanceSqr;
  416.                                         pNearestBoxEntity = pEntity;
  417.                                 }
  418.                         }
  419.                 }
  420.         }
  421.  
  422.         if (pNearestBoxEntity || pNearestDotEntity)
  423.         {
  424.                 //      CryLog ("[INTERACTION] Dot winner = '%s', box winner = '%s'!", pNearestDotEntity ? pNearestDotEntity->GetClass()->GetName() : "N/A", pNearestBoxEntity ? pNearestBoxEntity->GetClass()->GetName() : "N/A");
  425.  
  426.                 if (pNearestDotEntity == NULL)
  427.                 {
  428.                         pNearestDotEntity = pNearestBoxEntity;
  429.                         r = bestBoxResult;
  430.                 }
  431.  
  432.                 return true;
  433.         }
  434.  
  435.         return false;
  436. }
  437.  
  438. float CInteractor::LinePointDistanceSqr(const Line& line, const Vec3& point)
  439. {
  440.         Vec3 x0 = point;
  441.         Vec3 x1 = line.pointonline;
  442.         Vec3 x2 = line.pointonline + line.direction;
  443.  
  444.         return ((x2 - x1).Cross(x1 - x0)).GetLengthSquared() / (x2 - x1).GetLengthSquared();
  445. }
  446.  
  447. int CInteractor::PerformUsableTest(IEntity* pEntity) const
  448. {
  449.         if (pEntity && m_funcIsUsable)
  450.         {
  451.                 SmartScriptTable pScriptTable = pEntity->GetScriptTable();
  452.                 if (pScriptTable.GetPtr())
  453.                 {
  454.                         int usableIdx;
  455.                         bool scriptOk = Script::CallReturn(
  456.                           m_pGameRules->GetScriptSystem(),
  457.                           m_funcIsUsable,
  458.                           m_pGameRules,
  459.                           EntityIdToScript(GetEntityId()),
  460.                           EntityIdToScript(pEntity->GetId()),
  461.                           usableIdx);
  462.                         if (scriptOk && usableIdx)
  463.                         {
  464.                                 return usableIdx;
  465.                         }
  466.                 }
  467.         }
  468.         return 0;
  469. }
  470.  
  471. void CInteractor::PerformUsableTestOnEntities(TQueryVector& queryList)
  472. {
  473.         if (queryList.empty() || !m_funcAreUsable)
  474.                 return;
  475.  
  476.         //Prepare script parameters
  477.  
  478.         if (m_areUsableEntityList)
  479.         {
  480.                 m_areUsableEntityList->Clear();
  481.  
  482.                 SQueryResult queryResult;
  483.                 int tableIndex = 0;
  484.  
  485.                 TQueryVector::const_iterator endCit = queryList.end();
  486.                 for (TQueryVector::const_iterator elementCit = queryList.begin(); elementCit != endCit; ++elementCit)
  487.                 {
  488.                         const TQueryElement& element = *elementCit;
  489.  
  490.                         CRY_ASSERT(element.first);
  491.                         CRY_ASSERT(element.first->GetScriptTable());
  492.  
  493.                         m_areUsableEntityList->SetAt(++tableIndex, element.first->GetScriptTable());
  494.                 }
  495.  
  496.                 //Call script side
  497.                 SmartScriptTable scriptResults;
  498.                 bool scriptOk = Script::CallReturn(m_pGameRules->GetScriptSystem(), m_funcAreUsable, m_pGameRules, GetEntity()->GetScriptTable(), m_areUsableEntityList, scriptResults);
  499.  
  500.                 if (scriptOk && scriptResults)
  501.                 {
  502.                         const int resultCount = scriptResults->Count();
  503.                         const int queryCount = queryList.size();
  504.  
  505.                         CRY_ASSERT(queryCount <= resultCount);
  506.  
  507.                         if (queryCount <= resultCount)
  508.                         {
  509.                                 for (int i = 0; i < queryCount; ++i)
  510.                                 {
  511.                                         scriptResults->GetAt((i + 1), queryList[i].second.slotIdx);
  512.                                 }
  513.                         }
  514.  
  515.                 }
  516.         }
  517. }
  518.  
  519. bool CInteractor::PerformUsableTestAndCompleteIds(IEntity* pEntity, SQueryResult& r) const
  520. {
  521.         bool ok = false;
  522.         r.entityId = 0;
  523.         r.slotIdx = 0;
  524.         if (int usableIdx = PerformUsableTest(pEntity))
  525.         {
  526.                 r.entityId = pEntity->GetId();
  527.                 r.slotIdx = usableIdx;
  528.                 ok = true;
  529.         }
  530.         return ok;
  531. }
  532.  
  533. bool CInteractor::IsUsable(EntityId entityId) const
  534. {
  535.         IEntity* pEntity = m_pEntitySystem->GetEntity(entityId);
  536.  
  537.         static SQueryResult dummy;
  538.         return PerformUsableTestAndCompleteIds(pEntity, dummy);
  539. }
  540.  
  541. void CInteractor::UpdateTimers(EntityId newOverId, int usableIdx)
  542. {
  543.         CTimeValue now = m_pTimer->GetFrameStartTime();
  544.  
  545.         if (newOverId != m_nextOverId || usableIdx != m_nextOverIdx)
  546.         {
  547.                 m_nextOverId = newOverId;
  548.                 m_nextOverIdx = usableIdx;
  549.                 m_nextOverTime = now;
  550.         }
  551.         float compareTime = m_nextOverId ? m_useHoverTime : m_unUseHoverTime;
  552.         if ((m_nextOverId != m_overId || m_nextOverIdx != m_overIdx) && (now - m_nextOverTime).GetSeconds() > compareTime)
  553.         {
  554.                 m_overId = m_nextOverId;
  555.                 m_overIdx = m_nextOverIdx;
  556.                 m_overTime = m_nextOverTime;
  557.                 m_sentMessageHover = m_sentLongHover = false;
  558.                 if (m_funcOnNewUsable)
  559.                         Script::CallMethod(m_pGameRules, m_funcOnNewUsable, EntityIdToScript(GetEntityId()), EntityIdToScript(m_overId), m_overIdx);
  560.         }
  561.         if (m_funcOnUsableMessage && !m_sentMessageHover && (now - m_overTime).GetSeconds() > m_messageHoverTime)
  562.         {
  563.                 Script::CallMethod(m_pGameRules, m_funcOnUsableMessage, EntityIdToScript(GetEntityId()), EntityIdToScript(m_overId), m_overId, m_overIdx);
  564.  
  565.                 m_sentMessageHover = true;
  566.         }
  567.         if (m_funcOnLongHover && !m_sentLongHover && (now - m_overTime).GetSeconds() > m_longHoverTime)
  568.         {
  569.                 Script::CallMethod(m_pGameRules, m_funcOnLongHover, EntityIdToScript(GetEntityId()), EntityIdToScript(m_overId), m_overIdx);
  570.                 m_sentLongHover = true;
  571.         }
  572. }
  573.  
  574. void CInteractor::FullSerialize(TSerialize ser)
  575. {
  576.         ser.Value("useHoverTime", m_useHoverTime);
  577.         ser.Value("unUseHoverTime", m_unUseHoverTime);
  578.         ser.Value("messageHoverTime", m_messageHoverTime);
  579.         ser.Value("longHoverTime", m_longHoverTime);
  580.         ser.Value("queryMethods", m_queryMethods);
  581.         ser.Value("lastRadius", m_lastRadius);
  582.  
  583.         if (ser.GetSerializationTarget() == eST_Script && ser.IsReading())
  584.         {
  585.                 EntityId lockedById = 0, lockId = 0;
  586.                 int lockIdx = 0;
  587.                 ser.Value("locker", lockedById);
  588.                 if (lockedById)
  589.                 {
  590.                         if (m_lockedByEntityId && lockedById != m_lockedByEntityId)
  591.                         {
  592.                                 GameWarning("Attempt to change lock status by an entity that did not lock us originally");
  593.                         }
  594.                         else
  595.                         {
  596.                                 ser.Value("lockId", lockId);
  597.                                 ser.Value("lockIdx", lockIdx);
  598.                                 if (lockId && lockIdx)
  599.                                 {
  600.                                         m_lockedByEntityId = lockedById;
  601.                                         m_lockEntityId = lockId;
  602.                                         m_lockIdx = lockIdx;
  603.                                 }
  604.                                 else
  605.                                 {
  606.                                         m_lockedByEntityId = 0;
  607.                                         m_lockEntityId = 0;
  608.                                         m_lockIdx = 0;
  609.                                 }
  610.                         }
  611.                 }
  612.         }
  613.  
  614.         // the following should not be used as parameters
  615.         if (ser.GetSerializationTarget() != eST_Script)
  616.         {
  617.                 ser.Value("nextOverId", m_nextOverId);
  618.                 ser.Value("nextOverIdx", m_nextOverIdx);
  619.                 ser.Value("nextOverTime", m_nextOverTime);
  620.                 ser.Value("overId", m_overId);
  621.                 ser.Value("overIdx", m_overIdx);
  622.                 ser.Value("overTime", m_overTime);
  623.                 ser.Value("sentMessageHover", m_sentMessageHover);
  624.                 ser.Value("sentLongHover", m_sentLongHover);
  625.  
  626.                 //don't serialize lockEntity, it will lock on usage
  627.                 if (ser.IsReading())
  628.                 {
  629.                         m_lockedByEntityId = 0;
  630.                         m_lockEntityId = 0;
  631.                         m_lockIdx = 0;
  632.                 }
  633.         }
  634. }
  635.  
  636. bool CInteractor::NetSerialize(TSerialize ser, EEntityAspects aspect, uint8 profile, int flags)
  637. {
  638.         return true;
  639. }
  640.  
  641. void CInteractor::HandleEvent(const SGameObjectEvent&)
  642. {
  643.  
  644. }
  645.  
  646. void CInteractor::GetMemoryUsage(ICrySizer* pSizer) const
  647. {
  648.         pSizer->AddObject(this, sizeof(*this));
  649.         pSizer->AddObject(m_queryMethods);
  650.         pSizer->AddObject(m_pQuery);
  651. }
  652.  
  653. void CInteractor::PostSerialize()
  654. {
  655.         //?fix? : was invalid sometimes after QL
  656.         if (!m_pQuery)
  657.                 m_pQuery = (CWorldQuery*) GetGameObject()->AcquireExtension("WorldQuery");
  658.  
  659.         if (m_funcOnNewUsable)
  660.                 Script::CallMethod(m_pGameRules, m_funcOnNewUsable, EntityIdToScript(GetEntityId()), EntityIdToScript(m_overId), m_overIdx);
  661. }
  662.  
  663. bool CInteractor::IsEntityUsable(const IEntity* pEntity)
  664. {
  665.         CRY_ASSERT(pEntity);
  666.  
  667.         IEntityClass* pEntityClass = pEntity->GetClass();
  668.         TUsableClassesMap::const_iterator cit = m_usableEntityClasses.find(pEntityClass);
  669.         if (cit != m_usableEntityClasses.end())
  670.         {
  671.                 return (cit->second && pEntity->GetScriptTable() && !pEntity->IsHidden() && !pEntity->IsInvisible());
  672.         }
  673.         else
  674.         {
  675.                 bool hasIsUsableMethod = false;
  676.                 if (IScriptTable* pEntityScript = pEntity->GetScriptTable())
  677.                 {
  678.                         hasIsUsableMethod = pEntityScript->HaveValue("IsUsable");
  679.                 }
  680.                 m_usableEntityClasses.insert(TUsableClassesMap::value_type(pEntityClass, hasIsUsableMethod));
  681.  
  682.                 return hasIsUsableMethod && !pEntity->IsHidden() && !pEntity->IsInvisible();
  683.         }
  684. }
  685.  
downloadInteractor.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