BVB Source Codes

CRYENGINE Show VehicleDamageBehaviorDetachPart.cpp Source code

Return Download CRYENGINE: download VehicleDamageBehaviorDetachPart.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 "VehicleDamageBehaviorDetachPart.h"
  5.  
  6. #include <CryAnimation/ICryAnimation.h>
  7. #include "IVehicleSystem.h"
  8. #include "Vehicle.h"
  9. #include "VehiclePartBase.h"
  10. #include "VehiclePartAnimatedJoint.h"
  11.  
  12. //------------------------------------------------------------------------
  13. CVehicleDamageBehaviorDetachPart::CVehicleDamageBehaviorDetachPart()
  14.         : m_pVehicle(nullptr)
  15.         , m_detachedEntityId(0)
  16.         , m_pEffect(nullptr)
  17.         , m_pickableDebris(false)
  18.         , m_notifyMovement(false)
  19. {}
  20.  
  21. //------------------------------------------------------------------------
  22. CVehicleDamageBehaviorDetachPart::~CVehicleDamageBehaviorDetachPart()
  23. {
  24.         if (m_detachedEntityId != 0)
  25.         {
  26.                 gEnv->pEntitySystem->RemoveEntity(m_detachedEntityId);
  27.                 m_detachedEntityId = 0;
  28.         }
  29. }
  30.  
  31. //------------------------------------------------------------------------
  32. bool CVehicleDamageBehaviorDetachPart::Init(IVehicle* pVehicle, const CVehicleParams& table)
  33. {
  34.         m_pVehicle = static_cast<CVehicle*>(pVehicle);
  35.  
  36.         m_detachedEntityId = 0;
  37.  
  38.         //<DetachPartParams geometry="door2" direction="1.0,0.0,0.0" />
  39.  
  40.         if (CVehicleParams detachPartParams = table.findChild("DetachPart"))
  41.         {
  42.                 m_partName = detachPartParams.getAttr("part");
  43.                 detachPartParams.getAttr("notifyMovement", m_notifyMovement);
  44.  
  45.                 // Get optional custom particle effect
  46.                 if (detachPartParams.haveAttr("effect"))
  47.                         m_pEffect = gEnv->pParticleManager->FindEffect(detachPartParams.getAttr("effect"), "CVehicleDamageBehaviorDetachPart()");
  48.  
  49.                 detachPartParams.getAttr("pickable", m_pickableDebris);
  50.  
  51.                 return true;
  52.         }
  53.  
  54.         return false;
  55. }
  56.  
  57. //------------------------------------------------------------------------
  58. bool CVehicleDamageBehaviorDetachPart::Init(IVehicle* pVehicle, const string& partName, const string& effectName)
  59. {
  60.         m_pVehicle = static_cast<CVehicle*>(pVehicle);
  61.  
  62.         m_detachedEntityId = 0;
  63.  
  64.         m_partName = partName;
  65.  
  66.         // Get optional custom particle effect
  67.         if (!effectName.empty())
  68.                 m_pEffect = gEnv->pParticleManager->FindEffect(effectName.c_str(), "CVehicleDamageBehaviorDetachPart()");
  69.  
  70.         return true;
  71. }
  72.  
  73. //------------------------------------------------------------------------
  74. void CVehicleDamageBehaviorDetachPart::Reset()
  75. {
  76.         if (m_detachedEntityId)
  77.         {
  78.                 for (TDetachedStatObjs::iterator ite = m_detachedStatObjs.begin(), end = m_detachedStatObjs.end(); ite != end; ++ite)
  79.                 {
  80.                         CVehiclePartBase* pPartBase = ite->first;
  81.  
  82.                         if (IStatObj* pStatObj = ite->second)
  83.                         {
  84.                                 if (pPartBase)
  85.                                 {
  86.                                         pPartBase->SetStatObj(pStatObj);
  87.                                 }
  88.  
  89.                                 pStatObj->Release();
  90.                         }
  91.                 }
  92.  
  93.                 m_detachedStatObjs.clear();
  94.  
  95.                 if (GetISystem()->IsSerializingFile() != 1)
  96.                 {
  97.                         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  98.                         pEntitySystem->RemoveEntity(m_detachedEntityId, true);
  99.                 }
  100.  
  101.                 m_detachedEntityId = 0;
  102.         }
  103. }
  104.  
  105. //------------------------------------------------------------------------
  106. void CVehicleDamageBehaviorDetachPart::Serialize(TSerialize ser, EEntityAspects aspects)
  107. {
  108.         if (ser.GetSerializationTarget() != eST_Network)
  109.         {
  110.                 EntityId detachedId = m_detachedEntityId;
  111.                 ser.Value("m_detachedEntityId", detachedId);
  112.  
  113.                 if (ser.IsReading() && m_detachedEntityId != detachedId)
  114.                 {
  115.                         if (detachedId)
  116.                         {
  117.                                 m_detachedEntityId = detachedId;
  118.  
  119.                                 if (IEntity* pDetachedEntity = gEnv->pEntitySystem->GetEntity(m_detachedEntityId))
  120.                                 {
  121.                                         if (CVehiclePartBase* pPart = (CVehiclePartBase*)m_pVehicle->GetPart(m_partName.c_str()))
  122.                                         {
  123.                                                 MovePartToTheNewEntity(pDetachedEntity, pPart);
  124.                                         }
  125.                                 }
  126.                         }
  127.                         else
  128.                         {
  129.                                 Reset();
  130.                         }
  131.                 }
  132.         }
  133. }
  134.  
  135. //------------------------------------------------------------------------
  136. void CVehicleDamageBehaviorDetachPart::OnDamageEvent(EVehicleDamageBehaviorEvent event, const SVehicleDamageBehaviorEventParams& behaviorParams)
  137. {
  138.         if (event == eVDBE_Repair)
  139.                 return;
  140.  
  141.         if (!m_detachedEntityId && behaviorParams.componentDamageRatio >= 1.0f)
  142.         {
  143.                 CVehiclePartBase* pPart = (CVehiclePartBase*)m_pVehicle->GetPart(m_partName.c_str());
  144.                 if (!pPart || !pPart->GetStatObj())
  145.                         return;
  146.  
  147.                 if (max(1.f - behaviorParams.randomness, pPart->GetDetachProbability()) < cry_random(0.0f, 1.0f))
  148.                         return;
  149.  
  150.                 IEntity* pDetachedEntity = SpawnDetachedEntity();
  151.                 if (!pDetachedEntity)
  152.                         return;
  153.  
  154.                 m_detachedEntityId = pDetachedEntity->GetId();
  155.  
  156.                 const Matrix34& partWorldTM = pPart->GetWorldTM();
  157.                 pDetachedEntity->SetWorldTM(partWorldTM);
  158.  
  159.                 MovePartToTheNewEntity(pDetachedEntity, pPart);
  160.  
  161.                 SEntityPhysicalizeParams physicsParams;
  162.                 physicsParams.mass = pPart->GetMass();
  163.                 physicsParams.type = PE_RIGID;
  164.                 physicsParams.nSlot = 0;
  165.                 pDetachedEntity->Physicalize(physicsParams);
  166.  
  167.                 IPhysicalEntity* pPhysics = pDetachedEntity->GetPhysics();
  168.  
  169.                 if (pPhysics)
  170.                 {
  171.                         pe_params_part params;
  172.                         params.flagsOR = geom_collides | geom_floats;
  173.                         params.flagsColliderAND = ~geom_colltype3;
  174.                         params.flagsColliderOR = geom_colltype0;
  175.                         pPhysics->SetParams(&params);
  176.  
  177.                         pe_action_add_constraint ac;
  178.                         ac.flags = constraint_inactive | constraint_ignore_buddy;
  179.                         ac.pBuddy = m_pVehicle->GetEntity()->GetPhysics();
  180.                         ac.pt[0].Set(0, 0, 0);
  181.                         pPhysics->Action(&ac);
  182.  
  183.                         // after 1s, remove the constraint again
  184.                         m_pVehicle->SetTimer(-1, 1000, this);
  185.  
  186.                         // set the impulse
  187.                         const Vec3& velocity = m_pVehicle->GetStatus().vel;
  188.                         Vec3 baseForce = m_pVehicle->GetEntity()->GetWorldTM().TransformVector(pPart->GetDetachBaseForce());
  189.                         baseForce *= cry_random(6.0f, 10.0f);
  190.  
  191.                         pe_action_impulse actionImpulse;
  192.                         actionImpulse.impulse = physicsParams.mass * (velocity + baseForce);
  193.                         actionImpulse.angImpulse = physicsParams.mass * Vec3(cry_random(-1.0f, 1.0f), cry_random(-1.0f, 1.0f), cry_random(-1.0f, 1.0f));
  194.                         actionImpulse.iApplyTime = 1;
  195.  
  196.                         pPhysics->Action(&actionImpulse);
  197.                 }
  198.  
  199.                 // copy vehicle's material to new entity (fixes detaching parts from vehicles with different paints),
  200.                 // or specify the destroyed material if it exists
  201.  
  202.                 IStatObj* pExternalStatObj = pPart->GetExternalGeometry(false); // Get undamaged external geometry (if any)
  203.                 IMaterial* pMaterial = pExternalStatObj ? pExternalStatObj->GetMaterial() : m_pVehicle->GetEntity()->GetMaterial();
  204.  
  205.                 if (event == eVDBE_VehicleDestroyed || event == eVDBE_Hit)
  206.                 {
  207.                         if (pExternalStatObj)
  208.                         {
  209.                                 if (IStatObj* pStatObj = pPart->GetExternalGeometry(true))     // Try to get the destroyed, external geometry material
  210.                                         pMaterial = pStatObj->GetMaterial();
  211.                         }
  212.                         else if (m_pVehicle->GetDestroyedMaterial())  // If there is no external geometry, try the vehicle's destroyed material
  213.                         {
  214.                                 pMaterial = m_pVehicle->GetDestroyedMaterial();
  215.                         }
  216.                 }
  217.  
  218.                 pDetachedEntity->SetMaterial(pMaterial);
  219.  
  220.                 AttachParticleEffect(pDetachedEntity, m_pEffect);
  221.  
  222.                 if (m_notifyMovement)
  223.                 {
  224.                         SVehicleMovementEventParams params;
  225.                         params.iValue = pPart->GetIndex();
  226.                         m_pVehicle->GetMovement()->OnEvent(IVehicleMovement::eVME_PartDetached, params);
  227.                 }
  228.         }
  229. }
  230.  
  231. //------------------------------------------------------------------------
  232. IEntity* CVehicleDamageBehaviorDetachPart::SpawnDetachedEntity()
  233. {
  234.         IEntity* pVehicleEntity = m_pVehicle->GetEntity();
  235.         CRY_ASSERT(pVehicleEntity);
  236.  
  237.         // spawn the detached entity
  238.         char pPartName[128];
  239.         cry_sprintf(pPartName, "%s_DetachedPart_%s", pVehicleEntity->GetName(), m_partName.c_str());
  240.  
  241.         SEntitySpawnParams spawnParams;
  242.         spawnParams.sName = pPartName;
  243.         spawnParams.nFlags = ENTITY_FLAG_CLIENT_ONLY;
  244.         if (!m_pickableDebris)
  245.                 spawnParams.nFlags |= ENTITY_FLAG_NO_PROXIMITY;
  246.         spawnParams.pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("VehiclePartDetached");
  247.         if (!spawnParams.pClass)
  248.         {
  249.                 CRY_ASSERT(0);
  250.                 return NULL;
  251.         }
  252.  
  253.         return gEnv->pEntitySystem->SpawnEntity(spawnParams, true);
  254. }
  255.  
  256. //------------------------------------------------------------------------
  257. bool CVehicleDamageBehaviorDetachPart::MovePartToTheNewEntity(IEntity* pTargetEntity, CVehiclePartBase* pPartBase)
  258. {
  259.         if (!pPartBase)
  260.                 return false;
  261.  
  262.         IEntity* pVehicleEntity = m_pVehicle->GetEntity();
  263.         CRY_ASSERT(pVehicleEntity);
  264.  
  265.         assert(m_detachedEntityId == pTargetEntity->GetId());
  266.  
  267.         IStatObj* pStatObj = pPartBase->GetStatObj();
  268.         if (pStatObj)
  269.         {
  270.                 pStatObj->AddRef();
  271.         }
  272.         m_detachedStatObjs.push_back(TPartObjectPair(pPartBase, pStatObj));
  273.  
  274.         // place the geometry on the new entity
  275.         int slot = pTargetEntity->SetStatObj(pStatObj, -1, true, pPartBase->GetMass());
  276.  
  277.         const Matrix34& partTM = pPartBase->GetWorldTM();
  278.         Matrix34 localTM = pTargetEntity->GetWorldTM().GetInverted() * partTM;
  279.         pTargetEntity->SetSlotLocalTM(slot, localTM);
  280.  
  281.         pPartBase->SetStatObj(NULL);
  282.  
  283.         TVehiclePartVector& parts = m_pVehicle->GetParts();
  284.  
  285.         const CVehiclePartBase::TVehicleChildParts& children = pPartBase->GetChildParts();
  286.         for (CVehiclePartBase::TVehicleChildParts::const_iterator ite = children.begin(), end = children.end(); ite != end; ++ite)
  287.         {
  288.                 MovePartToTheNewEntity(pTargetEntity, (*ite));
  289.         }
  290.  
  291.         return true;
  292. }
  293.  
  294. //------------------------------------------------------------------------
  295. void CVehicleDamageBehaviorDetachPart::AttachParticleEffect(IEntity* pDetachedEntity, IParticleEffect* pEffect)
  296. {
  297.         if (pEffect)
  298.         {
  299.                 int slot = pDetachedEntity->LoadParticleEmitter(-1, pEffect, NULL, false, true);
  300.  
  301.                 if (IParticleEmitter* pParticleEmitter = pDetachedEntity->GetParticleEmitter(slot))
  302.                 {
  303.                         SpawnParams spawnParams;
  304.                         spawnParams.fSizeScale = cry_random(0.5f, 1.0f);
  305.  
  306.                         pParticleEmitter->SetSpawnParams(spawnParams);
  307.                 }
  308.         }
  309. }
  310.  
  311. //------------------------------------------------------------------------
  312. void CVehicleDamageBehaviorDetachPart::OnVehicleEvent(EVehicleEvent event, const SVehicleEventParams& params)
  313. {
  314.         assert(event == eVE_Timer);
  315.         assert(m_detachedEntityId);
  316.  
  317.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_detachedEntityId);
  318.         if (pEntity)
  319.         {
  320.                 pe_action_update_constraint ac;
  321.                 ac.bRemove = true;
  322.                 pEntity->GetPhysics()->Action(&ac);
  323.         }
  324. }
  325.  
  326. void CVehicleDamageBehaviorDetachPart::GetMemoryUsage(ICrySizer* s) const
  327. {
  328.         s->AddObject(this, sizeof(*this));
  329.         s->AddObject(m_partName);
  330. }
  331.  
  332. DEFINE_VEHICLEOBJECT(CVehicleDamageBehaviorDetachPart);
  333.  
downloadVehicleDamageBehaviorDetachPart.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