void CFlowConvoyNode::InitConvoyCoaches() { float distance = m_splitCoachIndex>0 ? m_splitDistanceOnPath : m_distanceOnPath; for (int i=m_coaches.size()-1; i>=0; --i) { if(m_splitCoachIndex>0 && i==m_splitCoachIndex-1) distance=m_distanceOnPath; // find the first train part end distance distance += m_coaches[i].m_coachOffset; m_coaches[i].m_distanceOnPath=distance; distance += m_coaches[i].m_coachOffset; IPhysicalEntity* pPhysics = m_coaches[i].m_pEntity->GetPhysics(); pe_params_flags flags; flags.flagsOR = pef_monitor_poststep|pef_fixed_damping; pPhysics->SetParams(&flags); pe_params_foreign_data pfd; pfd.iForeignFlagsOR = 0; //PFF_ALWAYS_VISIBLE; pPhysics->SetParams(&pfd); pe_simulation_params sp; sp.mass = -1; sp.damping = sp.dampingFreefall = 0; pPhysics->SetParams(&sp); } }
void CGameVolume_Water::CreatePhysicsArea(const uint32 segmentIndex, const Matrix34& baseMatrix, const Vec3* pVertices, uint32 vertexCount, const bool isRiver, const float streamSpeed) { //Destroy previous physics if any if(segmentIndex == 0) { DestroyPhysicsAreas(); } SWaterSegment& segment = m_segments[segmentIndex]; IWaterVolumeRenderNode* pWaterRenderNode = segment.m_pWaterRenderNode; Vec3 waterFlow(ZERO); CRY_ASSERT (segment.m_pWaterArea == NULL); CRY_ASSERT (pWaterRenderNode != NULL); pWaterRenderNode->SetMatrix( Matrix34::CreateIdentity() ); segment.m_pWaterArea = pWaterRenderNode->SetAndCreatePhysicsArea( &pVertices[0], vertexCount ); IPhysicalEntity* pWaterArea = segment.m_pWaterArea; if( pWaterArea ) { const Quat entityWorldRot = Quat(baseMatrix); pe_status_pos posStatus; pWaterArea->GetStatus( &posStatus ); const Vec3 areaPosition = baseMatrix.GetTranslation() + ((entityWorldRot * posStatus.pos) - posStatus.pos); pe_params_pos position; position.pos = areaPosition; position.q = entityWorldRot; pWaterArea->SetParams( &position); pe_params_buoyancy pb; pb.waterPlane.n = entityWorldRot * Vec3( 0, 0, 1 ); pb.waterPlane.origin = areaPosition; if(isRiver) { int i = segmentIndex; int j = vertexCount - 1 - segmentIndex; pb.waterFlow = ((pVertices[1]-pVertices[0]).GetNormalized() + (pVertices[2]-pVertices[3]).GetNormalized()) / 2.f * streamSpeed; } pWaterArea->SetParams( &pb); pe_params_foreign_data pfd; pfd.pForeignData = pWaterRenderNode; pfd.iForeignData = PHYS_FOREIGN_ID_WATERVOLUME; pfd.iForeignFlags = 0; pWaterArea->SetParams(&pfd); segment.m_physicsLocalAreaCenter = posStatus.pos; } }
void CPlayerStateJump::OnExit( CPlayer& player, const bool isHeavyWeapon ) { if (m_jumpAction) { m_jumpAction->TriggerExit(); m_jumpAction->Release(); m_jumpAction = NULL; } IPhysicalEntity* pPhysEnt = player.GetEntity()->GetPhysics(); if (pPhysEnt != NULL) { SAnimatedCharacterParams params = player.m_pAnimatedCharacter->GetParams(); pe_player_dynamics pd; pd.kAirControl = player.GetAirControl(); pd.kAirResistance = player.GetAirResistance(); params.inertia = player.GetInertia(); if(player.IsRemote() && (g_pGameCVars->pl_velocityInterpAirControlScale > 0)) { pd.kAirControl = g_pGameCVars->pl_velocityInterpAirControlScale; } pPhysEnt->SetParams(&pd); // Let Animated character handle the inertia player.SetAnimatedCharacterParams(params); } SetJumpState( player, JState_None ); }
//------------------------------------------------------------------------ void CParachute::PhysicalizeCanvas(bool enable) { IEntity* pCanvas = m_pEntitySystem->GetEntity(m_canvasId); if (!pCanvas) return; if (enable) { SEntityPhysicalizeParams params; params.type = PE_RIGID; params.mass = 0; pCanvas->Physicalize(params); IPhysicalEntity* pPhysics = pCanvas->GetPhysics(); if (!pPhysics) return; // add parachute physics geometry m_paraPhysIds.clear(); m_paraPhysIds.resize(8); for(int iCel=0; iCel<7; iCel++) { SWing *pCel = &m_aCels[iCel]; m_paraPhysIds.push_back( AddCel(pPhysics, iCel+1, pCel) ); pCel->fSurface = pCel->vSize.x * pCel->vSize.y; pCel->pLiftPointsMap = &m_LiftPointsMap; pCel->pDragPointsMap = &m_DragPointsMap; } Vec3 minExt(0.0f,0.0f,0.95f), maxExt(0.5f,0.3f,1.9f); m_paraPhysIds.push_back( AddBox(&minExt, &maxExt, 70.0f) ); pe_params_part pp; pp.partid = m_paraPhysIds.back(); pp.flagsAND = ~(geom_collides); pPhysics->SetParams(&pp); pe_status_dynamics stats; pPhysics->GetStatus(&stats); CryLog("Parachute mass: %f", stats.mass); } else { IPhysicalEntity* pPhysics = pCanvas->GetPhysics(); if (pPhysics) { // remove parachute geometry for (std::vector<int>::iterator it = m_paraPhysIds.begin(); it != m_paraPhysIds.end(); ++it) { pPhysics->RemoveGeometry(*it); } } m_paraPhysIds.clear(); } }
//------------------------------------------------------------------------ void CVehicleMovementHelicopter::Physicalize() { CVehicleMovementBase::Physicalize(); IPhysicalEntity * pPhysicalEntity = GetPhysics(); pe_params_flags pf; pf.flagsOR = pef_ignore_areas; pPhysicalEntity->SetParams(&pf); pe_simulation_params simParams; simParams.iSimClass = SC_ACTIVE_RIGID; simParams.damping = 0.0f; simParams.dampingFreefall = 0.0f; simParams.gravity = Vec3(0.0f, 0.0f, 0.0f); simParams.minEnergy = 0.0f; pPhysicalEntity->SetParams(&simParams); }
//------------------------------------------------------------------------ void CGunTurret::UpdatePhysics() { int slots[] = {eIGS_Aux0,eIGS_Aux1,eIGS_ThirdPerson}; int slots_num = 3; if(m_destroyed) { slots[1] = eIGS_Destroyed; slots_num = 2; } if(IEntity *pParent = GetEntity()->GetParent()) { IPhysicalEntity *pParentPhysics = pParent->GetPhysics(); IEntityPhysicalProxy *pPhysicsProxy = (IEntityPhysicalProxy *)GetEntity()->GetProxy(ENTITY_PROXY_PHYSICS); if(pParentPhysics && pPhysicsProxy) { Matrix34 localTM = GetEntity()->GetLocalTM(); localTM.OrthonormalizeFast(); Quat localQ = Quat(localTM); for(int i=0; i<slots_num; ++i) { pe_params_part params; params.partid = slots[i] + pPhysicsProxy->GetPartId0(); const Matrix34 &slotTM = GetEntity()->GetSlotLocalTM(slots[i], false); params.pos = slotTM.GetTranslation(); params.q = Quat(slotTM); params.pos = localTM * params.pos; params.q = localQ * params.q; pParentPhysics->SetParams(¶ms); } } } else { if(IPhysicalEntity *pPhysics = GetEntity()->GetPhysics()) { for(int i=0; i<slots_num; ++i) { pe_params_part params; params.partid = slots[i]; Matrix34 slotTM = GetEntity()->GetSlotLocalTM(slots[i], false); params.pMtx3x4 = &slotTM; pPhysics->SetParams(¶ms); } } } }
void CBaseGrabHandler::IgnoreCollision(EntityId eID,unsigned int flags,bool ignore) { IEntity *pGrab = gEnv->pEntitySystem->GetEntity(eID); IPhysicalEntity *ppGrab = pGrab ? pGrab->GetPhysics() : NULL; if(!ppGrab) return; if(ignore) { // NOTE Dez 14, 2006: <pvl> this whole block just fills in // a request structure and passes it to physics IEntity *pEnt = m_pActor->GetEntity(); pe_action_add_constraint ac; ac.flags = constraint_inactive|constraint_ignore_buddy; ac.pBuddy = pEnt->GetPhysics(); ac.pt[0].Set(0,0,0); ICharacterInstance *pCharacter = pEnt->GetCharacter(0); IPhysicalEntity *pPhysEnt = pCharacter?pCharacter->GetISkeletonPose()->GetCharacterPhysics(-1):NULL; if(pPhysEnt) { pe_simulation_params sp; pPhysEnt->GetParams(&sp); if(sp.iSimClass <= 2) ac.pBuddy = pPhysEnt; } ppGrab->Action(&ac); } else { // NOTE Dez 14, 2006: <pvl> the same as the other branch - just // fill in a request and pass it to the physics engine pe_action_update_constraint uc; uc.bRemove = 1; ppGrab->Action(&uc); } // NOTE Dez 14, 2006: <pvl> flag manipulation is basically a legacy // code - probably not used anymore, scheduled for removal. if(flags) { pe_params_part pp; pp.flagsAND = pp.flagsColliderAND = ~flags; pp.flagsOR = pp.flagsColliderOR = flags * (ignore?0:1); pe_status_nparts status_nparts; for(pp.ipart = ppGrab->GetStatus(&status_nparts)-1; pp.ipart>=0; pp.ipart--) ppGrab->SetParams(&pp); } }
void CPlayerStateUtil::PhySetFly( CPlayer& player ) { IPhysicalEntity* pPhysEnt = player.GetEntity()->GetPhysics(); if (pPhysEnt != NULL) { pe_player_dynamics pd; pd.bSwimming = true; pd.kAirControl = 1.0f; pd.kAirResistance = 0.0f; pd.gravity.zero(); pPhysEnt->SetParams(&pd); } }
void CPlayerStateUtil::PhySetNoFly( CPlayer& player, const Vec3& gravity ) { IPhysicalEntity* pPhysEnt = player.GetEntity()->GetPhysics(); if (pPhysEnt != NULL) { pe_player_dynamics pd; pd.kAirControl = player.GetAirControl(); pd.kAirResistance = player.GetAirResistance(); pd.bSwimming = false; pd.gravity = gravity; player.m_actorPhysics.gravity = gravity; pPhysEnt->SetParams(&pd); } }
//------------------------------------------------------------------------ void CVehicleMovementTank::SetLatFriction(float latFric) { // todo: do calculation per-wheel? IPhysicalEntity* pPhysics = GetPhysics(); int numWheels = m_pVehicle->GetWheelCount(); pe_params_wheel params; params.kLatFriction = latFric; for (int i=0; i<numWheels; ++i) { params.iWheel = i; pPhysics->SetParams(¶ms, THREAD_SAFE); } m_latFriction = latFric; }
//------------------------------------------------------------------------ bool CNetworkedPhysicsEntity::SetAspectProfile( EEntityAspects aspect, uint8 profile ) { bool bRetVal = false; if (aspect == eEA_Physics) { switch (profile) { case ePhys_PhysicalizedRigid: { if (m_physicsType!=ePhys_PhysicalizedRigid) { m_physicsParams.type = PE_RIGID; GetEntity()->Physicalize(m_physicsParams); m_physicsType = ePhys_PhysicalizedRigid; GetEntity()->GetPhysics()->SetParams(m_physicsParams.pBuoyancy); } bRetVal = true; break; } case ePhys_PhysicalizedStatic: { if (m_physicsType != ePhys_PhysicalizedStatic) { m_physicsParams.type = PE_STATIC; GetEntity()->Physicalize(m_physicsParams); m_physicsType = ePhys_PhysicalizedStatic; } bRetVal = true; break; } case ePhys_NotPhysicalized: { if (m_physicsType!=ePhys_NotPhysicalized) { SEntityPhysicalizeParams params; params.type = PE_NONE; GetEntity()->Physicalize(params); m_physicsType = ePhys_NotPhysicalized; } bRetVal = true; break; } default: { CryLog("Unsupported physicalization type in CNetworkedPhysicsEntity!"); } } } IPhysicalEntity * pPhysEnt = GetEntity()->GetPhysics(); if(pPhysEnt) { // Turn off some collisions // NB: by leaving pe_params_part.ipart undefined, all the geom flags will changed pe_params_part pp; pp.flagsAND = ~(geom_colltype_ray|geom_colltype_player|geom_colltype_explosion|geom_colltype_debris|geom_colltype_foliage_proxy); pPhysEnt->SetParams(&pp); pe_simulation_params psp; psp.damping = 0.5f; pPhysEnt->SetParams(&psp); //Add a bit of angular velocity so it doesn't look bizzare. pe_action_set_velocity physicsAction; physicsAction.w.Set((rnd()-0.5f)*15.0f, (rnd()-0.5f)*15.0f, (rnd()-0.5f)*15.0f); pPhysEnt->Action(&physicsAction); } return bRetVal; }
//------------------------------------------------------------------------ void CVehicleDamageBehaviorBlowTire::Activate(bool activate) { if (activate == m_isActive) return; if (activate && m_pVehicle->IsDestroyed()) return; if (activate) { // NOTE: stance and physics position when getting into vehicles is set wrong if (!gEnv->pSystem->IsSerializingFile()) DamagePlayers(); } IVehicleComponent* pComponent = m_pVehicle->GetComponent(m_component.c_str()); if (!pComponent) return; IVehiclePart* pPart = pComponent->GetPart(0); if (!pPart) return; // if IVehicleWheel available, execute full damage behavior. if null, only apply effects IVehicleWheel* pWheel = pPart->GetIWheel(); if (activate) { IEntity* pEntity = m_pVehicle->GetEntity(); IPhysicalEntity* pPhysics = pEntity->GetPhysics(); const Matrix34& wheelTM = pPart->GetLocalTM(false); const SVehicleStatus& status = m_pVehicle->GetStatus(); if (pWheel) { const pe_cargeomparams* pParams = pWheel->GetCarGeomParams(); // handle destroyed wheel pe_params_wheel wheelParams; wheelParams.iWheel = pWheel->GetWheelIndex(); wheelParams.minFriction = wheelParams.maxFriction = 0.5f * pParams->maxFriction; pPhysics->SetParams(&wheelParams); if (IVehicleMovement* pMovement = m_pVehicle->GetMovement()) { SVehicleMovementEventParams params; params.pComponent = pComponent; params.iValue = pWheel->GetWheelIndex(); pMovement->OnEvent(IVehicleMovement::eVME_TireBlown, params); } if (status.speed > 0.1f) { // add angular impulse pe_action_impulse angImp; float amount = m_pVehicle->GetMass() * status.speed * Random(0.25f, 0.45f) * -sgn(wheelTM.GetTranslation().x); angImp.angImpulse = pEntity->GetWorldTM().TransformVector(Vec3(0,0,amount)); pPhysics->Action(&angImp); } m_aiImmobilizedTimer = m_pVehicle->SetTimer(-1, AI_IMMOBILIZED_TIME*1000, this); } if (!gEnv->pSystem->IsSerializingFile()) { // add linear impulse pe_action_impulse imp; imp.point = pPart->GetWorldTM().GetTranslation(); float amount = m_pVehicle->GetMass() * Random(0.1f, 0.15f); if (pWheel) { amount *= max(0.5f, min(10.f, status.speed)); if (status.speed < 0.1f) amount = -0.5f*amount; } else amount *= 0.5f; imp.impulse = pEntity->GetWorldTM().TransformVector(Vec3(0,0,amount)); pPhysics->Action(&imp); // effect IParticleEffect* pEffect = gEnv->pParticleManager->FindEffect(TIRE_BLOW_EFFECT); if (pEffect) { int slot = pEntity->LoadParticleEmitter(-1, pEffect); if (slot > -1) { float rotation = pWheel ? 0.5f * gf_PI * -sgn(wheelTM.GetTranslation().x) : gf_PI; Matrix34 tm = Matrix34::CreateRotationZ(rotation); tm.SetTranslation(wheelTM.GetTranslation()); pEntity->SetSlotLocalTM(slot, tm); } } // remove affected decals { Vec3 pos = pPart->GetWorldTM().GetTranslation(); AABB aabb = pPart->GetLocalBounds(); float radius = aabb.GetRadius(); Vec3 vRadius(radius,radius,radius); AABB areaBox(pos-vRadius, pos+vRadius); IRenderNode * pRenderNode = NULL; if (IEntityRenderProxy *pRenderProxy = (IEntityRenderProxy*)pEntity->GetProxy(ENTITY_PROXY_RENDER)) pRenderNode = pRenderProxy->GetRenderNode(); gEnv->p3DEngine->DeleteDecalsInRange(&areaBox, pRenderNode); } } } else { if (pWheel) { // restore wheel properties IPhysicalEntity* pPhysics = m_pVehicle->GetEntity()->GetPhysics(); pe_params_wheel wheelParams; for (int i=0; i<m_pVehicle->GetWheelCount(); ++i) { const pe_cargeomparams* pParams = m_pVehicle->GetWheelPart(i)->GetIWheel()->GetCarGeomParams(); wheelParams.iWheel = i; wheelParams.bBlocked = 0; wheelParams.suspLenMax = pParams->lenMax; wheelParams.bDriving = pParams->bDriving; wheelParams.minFriction = pParams->minFriction; wheelParams.maxFriction = pParams->maxFriction; pPhysics->SetParams(&wheelParams); } if (IVehicleMovement* pMovement = m_pVehicle->GetMovement()) { SVehicleMovementEventParams params; params.pComponent = pComponent; params.iValue = pWheel->GetWheelIndex(); // reset the particle status pMovement->OnEvent(IVehicleMovement::eVME_TireRestored, params); } } m_aiImmobilizedTimer = -1; } m_isActive = activate; }
int CFlowConvoyNode::OnPhysicsPostStep(const EventPhys * pEvent) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); if(m_bFirstUpdate) return 0; //after QuickLoad OnPhysicsPostStep called before ProcessEvent const EventPhysPostStep *pPhysPostStepEvent = (const EventPhysPostStep *)pEvent; IPhysicalEntity *pEventPhysEnt = pPhysPostStepEvent->pEntity; Vec3 posBack, posFront, posCenter; for (size_t i = 0; i < m_coaches.size(); ++i) { IPhysicalEntity *pPhysEnt = m_coaches[i].m_pEntity->GetPhysics(); if (pEventPhysEnt == pPhysEnt) { if (m_ShiftTime > 0.0f) { m_speed = m_speed * (1.0f - breakValue * pPhysPostStepEvent->dt / m_MaxShiftTime); m_ShiftTime -= pPhysPostStepEvent->dt; } else { m_speed = m_speed + min(1.0f, (pPhysPostStepEvent->dt / 5.0f)) * (m_desiredSpeed - m_speed); } float speed = (m_splitCoachIndex > 0 && (int)i >= m_splitCoachIndex) ? m_splitSpeed : m_speed; float distance = (m_coaches[i].m_distanceOnPath += pPhysPostStepEvent->dt * speed); if(m_splitCoachIndex>0) {//train splitted if(i==m_splitCoachIndex-1) // update m_distanceOnPath for serialization m_distanceOnPath=distance-m_coaches[i].m_coachOffset; else if(i==m_coaches.size()-1) // update m_splitDistanceOnPath for serialization m_splitDistanceOnPath=distance-m_coaches[i].m_coachOffset; } else {//train in one piece if(i==m_coaches.size()-1)// update m_distanceOnPath for serialization m_distanceOnPath=distance-m_coaches[i].m_coachOffset; } posBack = m_path.GetPointAlongPath(distance - m_coaches[i].m_wheelDistance, m_coaches[i].m_backWheelIterator[0]); posFront = m_path.GetPointAlongPath(distance + m_coaches[i].m_wheelDistance, m_coaches[i].m_frontWheelIterator[0]); posCenter = (posBack+posFront)*0.5f; Vec3 posDiff = posFront - posBack; float magnitude = posDiff.GetLength(); if (magnitude > FLT_EPSILON) { posDiff *= 1.0f / magnitude; pe_params_pos ppos; ppos.pos = posCenter; ppos.q = Quat::CreateRotationVDir(posDiff); if (m_bXAxisFwd) ppos.q *= Quat::CreateRotationZ(gf_PI*-0.5f); pPhysEnt->SetParams(&ppos, 0 /* bThreadSafe=0 */); // as we are calling from the physics thread Vec3 futurePositionBack, futurePositionFront; futurePositionBack = m_path.GetPointAlongPath(distance + PATH_DERIVATION_TIME * speed - m_coaches[i].m_wheelDistance, m_coaches[i].m_backWheelIterator[1]); futurePositionFront = m_path.GetPointAlongPath(distance + PATH_DERIVATION_TIME * speed + m_coaches[i].m_wheelDistance, m_coaches[i].m_frontWheelIterator[1]); Vec3 futurePosDiff = futurePositionFront - futurePositionBack; magnitude = futurePosDiff.GetLength(); if (magnitude > FLT_EPSILON) { futurePosDiff *= 1.0f / magnitude; pe_action_set_velocity setVel; setVel.v = ((futurePositionBack+ futurePositionFront)*0.5f - posCenter) * (1.0f/PATH_DERIVATION_TIME); //Vec3 dir=(posFront-posBack).GetNormalized(); //Vec3 future_dir=(futurePositionFront-futurePositionBack).GetNormalized(); Vec3 w=posDiff.Cross(futurePosDiff); float angle=cry_asinf(w.GetLength()); setVel.w=(angle/PATH_DERIVATION_TIME)*w.GetNormalized(); pPhysEnt->Action(&setVel, 0 /* bThreadSafe=0 */); // as we are calling from the physics thread break; } } } } // Done processing once we reach end of path if (m_atEndOfPath) m_processNode = false; return 0; }
//------------------------------------------------------------------------ void CVehicleMovementHelicopter::OnEvent(EVehicleMovementEvent event, const SVehicleMovementEventParams& params) { switch (event) { case eVME_Repair: { if(params.fValue < 0.25) { m_damageActual = 0.0f; m_damage = 0.0f; } } break; case eVME_Collision: { if (0) { m_isEnginePowered = false; pe_simulation_params simParams; simParams.dampingFreefall = 0.01f; simParams.gravity = Vec3(0.0f, 0.0f, -9.8f); GetPhysics()->SetParams(&simParams); } } break; case eVME_GroundCollision: { const float stopOver = 1.0f; } break; case eVME_Damage: { if (!m_pVehicle->IsIndestructable()) { const float stopOver = 1.0f; m_damage = params.fValue; if (m_damage > 0.95f) { m_isEngineDisabled = true; m_isEnginePowered = false; StopExhaust(); StopSounds(); IPhysicalEntity * pPhysicalEntity = GetPhysics(); pe_action_impulse impulse; impulse.angImpulse = Vec3(0.1f, 100.f, 0.0f); pPhysicalEntity->Action(&impulse); pe_simulation_params simParams; simParams.dampingFreefall = 0.01f; simParams.gravity = Vec3(0.0f, 0.0f, -9.8f); pPhysicalEntity->SetParams(&simParams); SVehicleEventParams eventParams; eventParams.entityId = 0; m_pVehicle->BroadcastVehicleEvent(eVE_Destroyed, eventParams); if (m_pVehicle) { if (IEntity *entity = m_pVehicle->GetEntity()) { if (IAIObject *aiobject = entity->GetAI()) { aiobject->Event(AIEVENT_DISABLE, NULL); } } } } } } break; case eVME_WarmUpEngine: m_enginePower = m_enginePowerMax; break; //case eVME_Turbulence: // m_turbulence = max(m_turbulence, params.fValue); // break; default: CVehicleMovementBase::OnEvent(event, params); break; } }
void CPlayerStateJump::StartJump( CPlayer& player, const bool isHeavyWeapon, const float fVerticalSpeedModifier ) { const SActorPhysics& actorPhysics = player.GetActorPhysics(); const SPlayerStats& stats = *player.GetActorStats(); const float onGroundTime = 0.2f; float g = actorPhysics.gravity.len(); const float jumpHeightScale = 1.0f; const float jumpHeight = player.GetActorParams().jumpHeight * jumpHeightScale; float playerZ = player.GetEntity()->GetWorldPos().z; float expectedJumpEndHeight = playerZ + jumpHeight; pe_player_dimensions dimensions; IPhysicalEntity *pPhysics = player.GetEntity()->GetPhysics(); if (pPhysics && pPhysics->GetParams(&dimensions)) { float physicsBottom = dimensions.heightCollider - dimensions.sizeCollider.z; if (dimensions.bUseCapsule) { physicsBottom -= dimensions.sizeCollider.x; } expectedJumpEndHeight += physicsBottom; } float jumpSpeed = 0.0f; if (g > 0.0f) { jumpSpeed = sqrt_tpl(2.0f*jumpHeight*(1.0f/g)) * g; if( isHeavyWeapon ) { jumpSpeed *= g_pGameCVars->pl_movement.nonCombat_heavy_weapon_speed_scale; } } //this is used to easily find steep ground float slopeDelta = (Vec3Constants<float>::fVec3_OneZ - actorPhysics.groundNormal).len(); SetJumpState(player, JState_Jump); Vec3 jumpVec(ZERO); bool bNormalJump = true; player.PlaySound(CPlayer::ESound_Jump); OnSpecialMove(player, IPlayerEventListener::eSM_Jump); CCCPOINT_IF( player.IsClient(), PlayerMovement_LocalPlayerNormalJump); CCCPOINT_IF(!player.IsClient(), PlayerMovement_NonLocalPlayerNormalJump); { // This was causing the vertical jumping speed to be much slower. float verticalMult = max(1.0f - m_jumpLock, 0.3f); const Quat baseQuat = player.GetBaseQuat(); jumpVec += baseQuat.GetColumn2() * jumpSpeed * verticalMult; jumpVec.z += fVerticalSpeedModifier; #ifdef STATE_DEBUG if (g_pGameCVars->pl_debugInterpolation > 1) { CryWatch("Jumping: vec from player BaseQuat only = (%f, %f, %f)", jumpVec.x, jumpVec.y, jumpVec.z); } #endif if (g_pGameCVars->pl_adjustJumpAngleWithFloorNormal && actorPhysics.groundNormal.len2() > 0.0f) { float vertical = clamp_tpl((actorPhysics.groundNormal.z - 0.25f) / 0.5f, 0.0f, 1.0f); Vec3 modifiedJumpDirection = LERP(actorPhysics.groundNormal, Vec3(0,0,1), vertical); jumpVec = modifiedJumpDirection * jumpVec.len(); } #ifdef STATE_DEBUG if (g_pGameCVars->pl_debugInterpolation > 1) { CryWatch("Jumping (%f, %f, %f)", jumpVec.x, jumpVec.y, jumpVec.z); } #endif } NETINPUT_TRACE(player.GetEntityId(), jumpVec); FinalizeVelocity( player, jumpVec ); if (!player.IsRemote()) { player.HasJumped(player.GetMoveRequest().velocity); } IPhysicalEntity* pPhysEnt = player.GetEntity()->GetPhysics(); if (pPhysEnt != NULL) { SAnimatedCharacterParams params = player.m_pAnimatedCharacter->GetParams(); pe_player_dynamics pd; pd.kAirControl = player.GetAirControl()* g_pGameCVars->pl_jump_control.air_control_scale; pd.kAirResistance = player.GetAirResistance() * g_pGameCVars->pl_jump_control.air_resistance_scale; params.inertia = player.GetInertia() * g_pGameCVars->pl_jump_control.air_inertia_scale; if(player.IsRemote() && (g_pGameCVars->pl_velocityInterpAirControlScale > 0)) { pd.kAirControl = g_pGameCVars->pl_velocityInterpAirControlScale; } pPhysEnt->SetParams(&pd); // Let Animated character handle the inertia player.SetAnimatedCharacterParams(params); } #if 0 if (debugJumping) { Vec3 entityPos = m_player.GetEntity()->GetWorldPos(); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(entityPos, ColorB(255,255,255,255), entityPos, ColorB(255,255,0,255), 2.0f); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(entityPos+Vec3(0,0,2), ColorB(255,255,255,255), entityPos+Vec3(0,0,2) + desiredVel, ColorB(0,255,0,255), 2.0f); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(entityPos, ColorB(255,255,255,255), entityPos + jumpVec, ColorB(0,255,255,255), 2.0f); gEnv->pRenderer->DrawLabel(entityPos - entityRight * 1.0f + Vec3(0,0,3.0f), 1.5f, "Velo[%2.3f = %2.3f, %2.3f, %2.3f]", m_request.velocity.len(), m_request.velocity.x, m_request.velocity.y, m_request.velocity.z); } #endif m_expectedJumpEndHeight = expectedJumpEndHeight; m_bSprintJump = player.IsSprinting(); }
void CStickyProjectile::Stick(const SStickParams& stickParams) { if(!gEnv->bServer && ((m_flags&eSF_HandleLocally)==0)) return; // Must have physics. if(!stickParams.m_pTarget) return; // Don't stick to Breakables. if(ISurfaceType *pSurfaceType = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceType(stickParams.m_targetMatId)) { if (pSurfaceType->GetBreakability() == 1) return; } // Ignore water collision if ( CProjectile::GetMaterialLookUp().IsMaterial( stickParams.m_targetMatId, CProjectile::SMaterialLookUp::eType_Water ) ) return; // Don't stick to particles type physics. const int peType = stickParams.m_pTarget->GetType(); if( peType == PE_PARTICLE ) return; const int iForiegnData = stickParams.m_pTarget->GetiForeignData(); IEntity* pTargetEntity = iForiegnData==PHYS_FOREIGN_ID_ENTITY ? (IEntity*)stickParams.m_pTarget->GetForeignData(PHYS_FOREIGN_ID_ENTITY) : NULL; if( pTargetEntity ) { const EntityId targetEntityId = pTargetEntity->GetId(); // Don't stick to owner. if(targetEntityId==stickParams.m_ownerId) return; //Do not attach to other projectiles if(g_pGame->GetWeaponSystem()->GetProjectile(targetEntityId)) return; // Do Stick. if(!StickToEntity(stickParams, pTargetEntity)) return; } else { // Without an entity, we expect the object to not be moving. So if it isn't the terrain or a static, then don't stick to it. if( iForiegnData!=PHYS_FOREIGN_ID_TERRAIN && iForiegnData!=PHYS_FOREIGN_ID_STATIC ) return; // Do Stick. if(!StickToStatic(stickParams)) return; } ////////////////////////////////////////////////////////////////////////// IEntity* pProjectileEntity = stickParams.m_pProjectile->GetEntity(); if(CWeapon* pWeapon = stickParams.m_pProjectile->GetWeapon()) { pWeapon->OnProjectileCollided( pProjectileEntity->GetId(), stickParams.m_pTarget, stickParams.m_stickPosition ); } if((m_flags&eSF_HandleLocally)==0) { CHANGED_NETWORK_STATE(stickParams.m_pProjectile, eEA_GameServerStatic); } SendHitInfo(stickParams.m_pProjectile, pTargetEntity); IPhysicalEntity* pPhysEnt = pProjectileEntity->GetPhysics(); if(((m_flags&eSF_IsStuck)!=0) && pPhysEnt) { pe_params_part pp; pp.flagsAND = ~geom_colltype_explosion; pp.flagsColliderAND = ~geom_colltype_solid; pp.mass = 0.0f; pPhysEnt->SetParams(&pp); } }
void CVehicleWeaponControlled::Update(SEntityUpdateContext& ctx, int update) { IVehicle *pVehicle = m_vehicleId ? gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(m_vehicleId) : NULL; if (!m_vehicleId && GetEntity()->GetParent()) { IEntity *entity = GetEntity(); if (entity) { IEntity *parent = entity->GetParent(); if (parent) { m_vehicleId = parent->GetId(); pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(parent->GetId()); } } } if (pVehicle) { IVehiclePart *pPart = pVehicle->GetWeaponParentPart(GetEntityId()); if(pPart) { if(IVehiclePart *pParentPart = pPart->GetParent()) { CRY_ASSERT(pVehicle->GetEntity()); if(ICharacterInstance *characterInst = pVehicle->GetEntity()->GetCharacter(pParentPart->GetSlot())) { if(ISkeletonPose* pose = characterInst->GetISkeletonPose()) { IDefaultSkeleton& rIDefaultSkeleton = characterInst->GetIDefaultSkeleton(); int16 joint = rIDefaultSkeleton.GetJointIDByName(pPart->GetName()); const QuatT &jQuat = pose->GetAbsJointByID(joint); Matrix34 localT(jQuat); localT.SetTranslation(jQuat.t/* - Vec3(0.0f, 0.75f, 0.0f)*/); Matrix34 vehicleWorldTm = pVehicle->GetEntity()->GetWorldTM(); Matrix34 mat = vehicleWorldTm * localT; Vec3 vehicleSide2 = pPart->GetParent()->GetLocalTM(true, true).GetTranslation(); CPlayer *pl = this->GetOwnerPlayer(); Matrix33 mat2; if (!m_destination.IsEquivalent(ZERO)) { Vec3 diff = GetDestination() - mat.GetTranslation(); //pPart->GetWorldTM().GetTranslation(); diff.Normalize(); Matrix33 loc(mat); loc.Invert(); Vec3 diffLocal = loc.TransformVector(diff); Matrix33 desMat; desMat.SetRotationVDir(diffLocal, 0.0f); Vec3 test = GetEntity()->GetLocalTM().GetColumn0(); Ang3 testTM(desMat); float za = testTM.x - m_Angles.x; za = (za < 0.0f) ? -gf_PI : gf_PI; za *= 0.05f * ctx.fFrameTime; m_Angles.x += za; Limit(m_Angles.x, -gf_PI * 0.33f, gf_PI * 0.33f); if (testTM.z > m_Angles.z + 0.05f) { m_Angles.z += gf_PI * factor1 * ctx.fFrameTime; } else if (testTM.z < m_Angles.z - 0.05f) { m_Angles.z -= gf_PI * factor1 * ctx.fFrameTime; } else { m_Angles.z = testTM.z; } Limit(m_Angles.z, -gf_PI * 0.33f, gf_PI * 0.33f); mat2.SetRotationXYZ(m_Angles); } else { if (!m_FireBlocked) { m_Angles.x = m_Angles.x - ctx.fFrameTime * factor2 * m_Angles.x; m_Angles.z = m_Angles.z - ctx.fFrameTime * factor2 * m_Angles.z; } mat2.SetRotationXYZ(m_Angles); } mat = mat * mat2; GetEntity()->SetWorldTM(mat); if (pl) { Matrix34 worldGunMat = vehicleWorldTm * localT; if (!pl->IsDead()) { Vec3 trans = worldGunMat.GetTranslation() - worldGunMat.GetColumn2() * 0.7f; worldGunMat.SetTranslation(trans); pl->GetEntity()->SetWorldTM(worldGunMat); float dot = mat.GetColumn1().dot(worldGunMat.GetColumn0()); Update3PAnim(pl, 0.5f - dot * 0.5f, ctx.fFrameTime, mat); } else { ICharacterInstance* pCharacter = pl->GetEntity()->GetCharacter(0); int boneId = pCharacter ? pCharacter->GetIDefaultSkeleton().GetJointIDByName("Spine03") : 7; pl->LinkToMountedWeapon(0); if (IVehicleSeat* seat = pVehicle->GetSeatForPassenger(pl->GetEntityId())) { seat->Exit(false, true); } Matrix33 rot(worldGunMat); Vec3 offset(0.0f, 0.0f, 0.70f); Vec3 transformedOff = rot.TransformVector(offset); Vec3 trans = worldGunMat.GetTranslation(); trans -= transformedOff; worldGunMat.SetTranslation(trans); pl->GetEntity()->SetWorldTM(worldGunMat); pl->GetEntity()->SetPos(worldGunMat.GetTranslation()); //worldGunMat.GetTranslation()); pl->RagDollize(true); if (boneId > -1) { IPhysicalEntity *physEnt = pl->GetEntity()->GetPhysics(); if (physEnt) { pe_simulation_params simulationParams; physEnt->GetParams(&simulationParams); pe_params_pos pos; pos.pos = GetEntity()->GetPos(); physEnt->SetParams(&pos); pe_action_impulse impulse; impulse.ipart = boneId; impulse.angImpulse = Vec3(0.0f, 0.0f, 1.0f); impulse.impulse = worldGunMat.GetColumn1() * -1.5f * simulationParams.mass; physEnt->Action(&impulse); } } StopUse(GetOwnerId()); SetOwnerId(0); StopFire(); m_FireBlocked = true; } // IsDead } // pl } // pose } // characterInst } // pParentPart } // pPart } // pVehicle Base::Update(ctx, update); RequireUpdate(eIUS_General); }
void CPickAndThrowProxy::Physicalize() { IEntity* pPlayerEntity = m_player.GetEntity(); IPhysicalEntity* pPlayerPhysics = pPlayerEntity->GetPhysics(); const bool bPhysicsChanged = (pPlayerPhysics != m_pLastPlayerPhysics); // Don't create it again if already exists and its associated physic entity is the same if ((m_pPickNThrowProxy && !bPhysicsChanged) || !g_pGameCVars->pl_pickAndThrow.useProxies) return; CRY_ASSERT(m_pParams != NULL); if (!m_pParams) return; if (bPhysicsChanged) Unphysicalize(); pe_params_pos pp; pp.pos = pPlayerEntity->GetWorldPos(); pp.iSimClass = SC_ACTIVE_RIGID; IPhysicalEntity* pPickNThrowProxy = gEnv->pPhysicalWorld->CreatePhysicalEntity(PE_ARTICULATED, &pp, pPlayerEntity, PHYS_FOREIGN_ID_ENTITY); phys_geometry *pGeom = NULL; switch(m_pParams->proxyShape) { case ePS_Capsule : { primitives::capsule prim; prim.axis.Set(0,0,1); prim.center.zero(); prim.r = m_pParams->fRadius; prim.hh = m_pParams->fHeight; IGeometry *pPrimGeom = gEnv->pPhysicalWorld->GetGeomManager()->CreatePrimitive(primitives::capsule::type, &prim); pGeom = gEnv->pPhysicalWorld->GetGeomManager()->RegisterGeometry(pPrimGeom, 0); pGeom->nRefCount = 0; pPrimGeom->Release(); } break; case ePS_Sphere : { primitives::sphere prim; prim.center.zero(); prim.r = m_pParams->fRadius; IGeometry *pPrimGeom = gEnv->pPhysicalWorld->GetGeomManager()->CreatePrimitive(primitives::sphere::type, &prim); pGeom = gEnv->pPhysicalWorld->GetGeomManager()->RegisterGeometry(pPrimGeom, 0); pGeom->nRefCount = 0; pPrimGeom->Release(); } break; case ePS_Cylinder : { primitives::cylinder prim; prim.axis.Set(0,0,1); prim.center.zero(); prim.r = m_pParams->fRadius; prim.hh = m_pParams->fHeight; IGeometry *pPrimGeom = gEnv->pPhysicalWorld->GetGeomManager()->CreatePrimitive(primitives::cylinder::type, &prim); pGeom = gEnv->pPhysicalWorld->GetGeomManager()->RegisterGeometry(pPrimGeom, 0); pGeom->nRefCount = 0; pPrimGeom->Release(); } break; default: CRY_ASSERT_MESSAGE(false, "Invalid proxy shape?"); } if (pGeom) { CRY_ASSERT(pPlayerEntity->GetPhysics() && (pPlayerEntity->GetPhysics()->GetType() == PE_LIVING)); pe_params_articulated_body pab; pab.pHost = pPlayerPhysics; m_pLastPlayerPhysics = pPlayerPhysics; pab.posHostPivot = m_pParams->vPosPivot; pab.bGrounded = 1; pab.nJointsAlloc = 1; pPickNThrowProxy->SetParams(&pab); pe_articgeomparams gp; gp.pos.zero(); gp.flags = CPickAndThrowProxy::geom_colltype_proxy; gp.flagsCollider = 0; gp.mass = 0.0f; pPickNThrowProxy->AddGeometry(pGeom, &gp); m_pPickNThrowProxy = pPickNThrowProxy; } }
void CVehicleMovementHelicopter::ProcessAI(const float deltaTime) { FUNCTION_PROFILER( GetISystem(), PROFILE_GAME ); CryAutoCriticalSection lk(m_lock); SVehiclePhysicsStatus* physStatus = &m_physStatus[k_physicsThread]; if (m_arcade.m_handling.maxSpeedForward>0.f) // Use the new handling code { //ResetActions(); m_movementAction.Clear(); m_movementAction.isAI = true; SVehiclePhysicsHelicopterProcessAIParams params; params.pPhysStatus = physStatus; params.pInputAction = &m_inputAction; params.pAiRequest = &m_aiRequest; params.dt = deltaTime; params.aiRequiredVel = m_CurrentVel; params.aiCurrentSpeed = m_CurrentSpeed; params.aiYawResponseScalar = m_yawResponseScalar; m_yawResponseScalar = 1.f; // Use helper class to process the AI input // It will return a requested velocity, and change the input m_arcade.ProcessAI(params); // Get the output velocity m_CurrentVel = params.aiRequiredVel; m_CurrentSpeed = params.aiCurrentSpeed; return; } ////////////////////// OLD DEPRECATED CODE :( ////////////////////////////////// m_movementAction.Clear(); ResetActions(); // Our current state const Vec3 worldPos = physStatus->pos; const Matrix33 worldMat( physStatus->q); const Matrix33 localMat( physStatus->q.GetInverted()); const Ang3 worldAngles = Ang3::GetAnglesXYZ(worldMat); const Ang3 localAngles = Ang3::GetAnglesXYZ(localMat); const Vec3 currentVel = physStatus->v; const Vec3 currentVel2D(currentVel.x, currentVel.y, 0.0f); m_CurrentSpeed = m_CurrentVel.len(); //currentVel.len(); float currentSpeed2d = currentVel2D.len(); // +ve direction mean rotation anti-clocwise about the z axis - 0 means along y float currentDir = worldAngles.z; // to avoid singularity const Vec3 vWorldDir = worldMat.GetRow(1); const Vec3 vSideWays = worldMat.GetRow(0); const Vec3 vWorldDir2D = Vec3( vWorldDir.x, vWorldDir.y, 0.0f ).GetNormalizedSafe(); // Our inputs float desiredSpeed = m_aiRequest.HasDesiredSpeed() ? m_aiRequest.GetDesiredSpeed() : 0.0f; Limit(desiredSpeed, -m_maxSpeed, m_maxSpeed); const Vec3 desiredMoveDir = m_aiRequest.HasMoveTarget() ? (m_aiRequest.GetMoveTarget() - worldPos).GetNormalizedSafe() : vWorldDir; Vec3 desiredMoveDir2D = Vec3(desiredMoveDir.x, desiredMoveDir.y, 0.0f); desiredMoveDir2D = desiredMoveDir2D.GetNormalizedSafe(desiredMoveDir2D); const Vec3 desiredVel = desiredMoveDir * desiredSpeed; const Vec3 desiredVel2D(desiredVel.x, desiredVel.y, 0.0f); Vec3 desiredLookDir(desiredMoveDir); if (m_aiRequest.HasDesiredBodyDirectionAtTarget()) { desiredLookDir = m_aiRequest.GetDesiredBodyDirectionAtTarget().GetNormalizedSafe(desiredMoveDir); } else if (m_aiRequest.HasLookTarget()) { desiredLookDir = (m_aiRequest.GetLookTarget() - worldPos).GetNormalizedSafe(desiredMoveDir); } //const Vec3 desiredLookDir = m_aiRequest.HasLookTarget() ? (m_aiRequest.GetLookTarget() - worldPos).GetNormalizedSafe() : desiredMoveDir; const Vec3 desiredLookDir2D = Vec3(desiredLookDir.x, desiredLookDir.y, 0.0f).GetNormalizedSafe(vWorldDir2D); Vec3 prediction = m_aiRequest.HasBodyTarget() ? m_aiRequest.GetBodyTarget() : ZERO; prediction = (prediction.IsEquivalent(ZERO)) ? desiredMoveDir2D : prediction - worldPos; prediction.z = 0.0f; float speedLimit = prediction.GetLength2D(); if(speedLimit > 0.0f) { prediction *= 1.0f / speedLimit; } Vec3 tempDir = currentVel2D.IsEquivalent(ZERO) ? localMat.GetRow(1) : currentVel2D; tempDir.z = 0.0f; tempDir.NormalizeFast(); float dotProd = tempDir.dot(prediction); Limit(dotProd, FLT_EPSILON, 1.0f); float accel = m_enginePowerMax * min(2.0f, 1.0f / dotProd); // * dotProd; if (!m_aiRequest.HasDesiredBodyDirectionAtTarget()) { dotProd *= dotProd; dotProd *= dotProd; float tempf = min(max(speedLimit * speedLimit, 2.0f), m_maxSpeed * dotProd); Limit(desiredSpeed, -tempf, tempf); } else if (dotProd < 0.0125f) { Limit(desiredSpeed, -m_maxSpeed * 0.25f, m_maxSpeed * 0.25f); } float posNeg = (float)__fsel(desiredSpeed - m_CurrentSpeed, 1.0f, -5.0f); if (desiredVel2D.GetLengthSquared() > FLT_EPSILON) { m_CurrentSpeed = m_CurrentSpeed + posNeg * accel * deltaTime; } else { m_CurrentSpeed = m_CurrentSpeed + posNeg * accel * deltaTime; } if (posNeg > 0.0f && m_CurrentSpeed > desiredSpeed) { m_CurrentSpeed = desiredSpeed; } else if (posNeg < 0.0f && m_CurrentSpeed < desiredSpeed) { m_CurrentSpeed = desiredSpeed; } // ---------------------------- Rotation ---------------------------- float desiredDir = (desiredLookDir2D.GetLengthSquared() > 0.0f) ? atan2f(-desiredLookDir2D.x, desiredLookDir2D.y) : atan2f(-vWorldDir2D.x, vWorldDir2D.y); while (currentDir < desiredDir - gf_PI) currentDir += 2.0f * gf_PI; while (currentDir > desiredDir + gf_PI) currentDir -= 2.0f * gf_PI; // ---------------------------- Yaw ---------------------------- Ang3 dirDiff(0.0f, 0.0f, desiredDir - currentDir); dirDiff.RangePI(); float absDiff = fabsf(dirDiff.z); float rotSpeed = (float)__fsel(dirDiff.z, m_yawPerRoll, -m_yawPerRoll); m_actionYaw = m_actionYaw + deltaTime * (rotSpeed - m_actionYaw); float temp = fabsf(m_actionYaw); float multiplier = ((absDiff / (temp + 0.001f)) + 1.0f) * 0.5f; m_actionYaw *= (float)__fsel(absDiff - temp, 1.0f, multiplier); // ---------------------------- Yaw ------------------------------ m_CurrentVel = desiredMoveDir * m_CurrentSpeed; // ---------------------------- Pitch ---------------------------- if (m_CurrentVel.GetLengthSquared2D() > 0.1f) { CalculatePitch(worldAngles, desiredMoveDir, currentSpeed2d, desiredSpeed, deltaTime); } else { Quat rot; rot.SetRotationVDir(desiredLookDir, 0.0f); float desiredXRot = Ang3::GetAnglesXYZ(rot).x + m_steeringDamage.x; m_actionPitch = worldAngles.x + (desiredXRot - worldAngles.x) * deltaTime/* * 10.0f*/; Limit(m_actionPitch, -m_maxPitchAngle * 2.0f, m_maxPitchAngle * 2.0f); } // ---------------------------- Roll ---------------------------- float rollSpeed = GetRollSpeed(); rollSpeed *= deltaTime; rollSpeed = (float)__fsel(absDiff - rollSpeed, rollSpeed, absDiff); float roll =(float) __fsel(dirDiff.z, -rollSpeed, rollSpeed); float speedPerUnit = 1.5f; float desiredRollSpeed = absDiff * speedPerUnit * (float)__fsel(dirDiff.z, 1.0f, -1.0f); desiredRollSpeed = -m_actionYaw * 2.5f; desiredRollSpeed += m_steeringDamage.y; m_actionRoll = m_actionRoll + deltaTime * (desiredRollSpeed - m_actionRoll); Limit(m_actionRoll, -m_maxRollAngle + m_steeringDamage.y, m_maxRollAngle - m_steeringDamage.y); m_actionRoll *= m_rollDamping; // ---------------------------- Roll ---------------------------- // ---------------------------- Convert and apply ---------------------------- Ang3 angles(m_actionPitch, m_actionRoll, worldAngles.z + deltaTime * m_actionYaw); pe_params_pos paramPos; paramPos.q.SetRotationXYZ(angles); paramPos.q.Normalize(); IPhysicalEntity * pPhysicalEntity = GetPhysics(); pPhysicalEntity->SetParams(¶mPos, 1); pe_action_set_velocity vel; vel.v = m_CurrentVel + m_netPosAdjust; pPhysicalEntity->Action(&vel, 1); // ---------------------------- Convert and apply ---------------------------- m_rpmScale = max(0.2f, cry_fabsf(m_CurrentSpeed / m_maxSpeed)); }
//------------------------------------------------------------------------ void CVehicleDamageBehaviorDetachPart::OnDamageEvent(EVehicleDamageBehaviorEvent event, const SVehicleDamageBehaviorEventParams& behaviorParams) { if (event == eVDBE_Repair) return; if (!m_detachedEntityId && behaviorParams.componentDamageRatio >= 1.0f) { CVehiclePartBase* pPart = (CVehiclePartBase*)m_pVehicle->GetPart(m_partName.c_str()); if (!pPart || !pPart->GetStatObj()) return; if (max(1.f-behaviorParams.randomness, pPart->GetDetachProbability()) < cry_random(0.0f, 1.0f)) return; IEntity* pDetachedEntity = SpawnDetachedEntity(); if (!pDetachedEntity) return; m_detachedEntityId = pDetachedEntity->GetId(); const Matrix34& partWorldTM = pPart->GetWorldTM(); pDetachedEntity->SetWorldTM(partWorldTM); MovePartToTheNewEntity(pDetachedEntity, pPart); SEntityPhysicalizeParams physicsParams; physicsParams.mass = pPart->GetMass(); physicsParams.type = PE_RIGID; physicsParams.nSlot = 0; pDetachedEntity->Physicalize(physicsParams); IPhysicalEntity* pPhysics = pDetachedEntity->GetPhysics(); if (pPhysics) { pe_params_part params; params.flagsOR = geom_collides|geom_floats; params.flagsColliderAND = ~geom_colltype3; params.flagsColliderOR = geom_colltype0; pPhysics->SetParams(¶ms); pe_action_add_constraint ac; ac.flags = constraint_inactive|constraint_ignore_buddy; ac.pBuddy = m_pVehicle->GetEntity()->GetPhysics(); ac.pt[0].Set(0,0,0); pPhysics->Action(&ac); // after 1s, remove the constraint again m_pVehicle->SetTimer(-1, 1000, this); // set the impulse const Vec3& velocity = m_pVehicle->GetStatus().vel; Vec3 baseForce = m_pVehicle->GetEntity()->GetWorldTM().TransformVector(pPart->GetDetachBaseForce()); baseForce *= cry_random(6.0f, 10.0f); pe_action_impulse actionImpulse; actionImpulse.impulse = physicsParams.mass * (velocity + baseForce); actionImpulse.angImpulse = physicsParams.mass * Vec3(cry_random(-1.0f,1.0f), cry_random(-1.0f,1.0f), cry_random(-1.0f,1.0f)); actionImpulse.iApplyTime = 1; pPhysics->Action(&actionImpulse); } // copy vehicle's material to new entity (fixes detaching parts from vehicles with different paints), // or specify the destroyed material if it exists IStatObj* pExternalStatObj = pPart->GetExternalGeometry(false); // Get undamaged external geometry (if any) IMaterial *pMaterial = pExternalStatObj ? pExternalStatObj->GetMaterial() : m_pVehicle->GetEntity()->GetMaterial(); if(event == eVDBE_VehicleDestroyed || event == eVDBE_Hit) { if (pExternalStatObj) { if (IStatObj* pStatObj = pPart->GetExternalGeometry(true)) // Try to get the destroyed, external geometry material pMaterial = pStatObj->GetMaterial(); } else if (m_pVehicle->GetDestroyedMaterial()) // If there is no external geometry, try the vehicle's destroyed material { pMaterial = m_pVehicle->GetDestroyedMaterial(); } } pDetachedEntity->SetMaterial(pMaterial); AttachParticleEffect(pDetachedEntity, m_pEffect); if (m_notifyMovement) { SVehicleMovementEventParams params; params.iValue = pPart->GetIndex(); m_pVehicle->GetMovement()->OnEvent(IVehicleMovement::eVME_PartDetached, params); } } }