//------------------------------------------------------------------------ void CVehicleMovementHelicopter::PreProcessMovement(const float deltaTime) { IPhysicalEntity *pPhysics = GetPhysics(); assert(pPhysics); float gravity; pe_simulation_params paramsSim; if(pPhysics->GetParams(¶msSim)) gravity = abs(paramsSim.gravity.z); else gravity = 9.8f; m_engineForce = gravity * m_enginePower; const Matrix33 tm(m_PhysPos.q); const Ang3 angles = Ang3::GetAnglesXYZ(tm); m_workingUpDir = m_engineUpDir; //m_workingUpDir += (m_rotorDiskTiltScale * Vec3(m_actionRoll, -m_actionPitch, 0.0f)); m_workingUpDir += (m_rotorDiskTiltScale * Vec3(angles.y, -angles.x, 0.0f)); m_workingUpDir = tm * m_workingUpDir; m_workingUpDir.NormalizeSafe(); if(m_noHoveringTimer > 0.0f) m_noHoveringTimer -= deltaTime; }
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); } }
bool CStickyProjectile::IsValid() const { if (!IsStuck()) return false; if(m_parentId == 0) return true; pe_params_part part; part.partid = m_stuckPartId; IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_parentId); if(pEntity) { if (pEntity->IsHidden()) { return false; } if(ICharacterInstance* pCharacter = pEntity->GetCharacter(0)) { if(ISkeletonPose* pSkel = pCharacter->GetISkeletonPose()) { IPhysicalEntity* pSkelPhysics = pSkel->GetCharacterPhysics(); if (pSkelPhysics) { return pSkelPhysics->GetParams(&part) != 0; } } } else { IPhysicalEntity* pPhysics = pEntity->GetPhysics(); if (pPhysics) { return pPhysics->GetParams(&part) != 0; } } } return false; }
void CPlayerStateFly::OnExit( CPlayer& player ) { player.CreateScriptEvent("printhud",0,"FlyMode/NoClip OFF"); pe_player_dynamics simPar; IPhysicalEntity* piPhysics = player.GetEntity()->GetPhysics(); if (!piPhysics || piPhysics->GetParams(&simPar) == 0) { return; } CPlayerStateUtil::PhySetNoFly( player, simPar.gravity ); }
//----------------------------------------------------------------------- void CSpectacularKill::DeathBlow(CActor& targetActor) { CRY_ASSERT_MESSAGE(m_isBusy, "spectacular kill should be in progress when triggering the death blow"); if (!m_isBusy) return; if (targetActor.IsDead()) return; Vec3 targetDir = targetActor.GetEntity()->GetForwardDir(); { HitInfo hitInfo; hitInfo.shooterId = m_pOwner->GetEntityId(); hitInfo.targetId = targetActor.GetEntityId(); hitInfo.damage = 99999.0f; // CERTAIN_DEATH hitInfo.dir = targetDir; hitInfo.normal = -hitInfo.dir; // this has to be in an opposite direction from the hitInfo.dir or the hit is ignored as a 'backface' hit hitInfo.type = CGameRules::EHitType::StealthKill; g_pGame->GetGameRules()->ClientHit(hitInfo); } // WARNING: RagDollize resets the entity's rotation! // [7/30/2010 davidr] FixMe: If the entity isn't dead here (because is immortal or any other reason) ragdollizing it will // leave it on an inconsistent state (usually only reproducible on debug scenarios) targetActor.GetGameObject()->SetAspectProfile(eEA_Physics, eAP_Ragdoll); // Give a small nudge in the hit direction to make the target fall over const SSpectacularKillParams* pSpectacularKillParams = GetParamsForClass(targetActor.GetEntity()->GetClass()); CRY_ASSERT(pSpectacularKillParams); if (pSpectacularKillParams && (pSpectacularKillParams->impulseScale > 0.0f) && (pSpectacularKillParams->impulseBone != -1)) { const float killDeathBlowVelocity = pSpectacularKillParams->impulseScale; // desired velocity after impulse in meters per second IPhysicalEntity* pTargetPhysics = targetActor.GetEntity()->GetPhysics(); if (pTargetPhysics) { pe_simulation_params simulationParams; pTargetPhysics->GetParams(&simulationParams); pe_action_impulse impulse; impulse.partid = pSpectacularKillParams->impulseBone; impulse.impulse = targetDir*killDeathBlowVelocity*simulationParams.mass; // RagDollize reset the entity's rotation so I have to use the value I cached earlier pTargetPhysics->Action(&impulse); } } m_deathBlowState = eDBS_Done; }
void CGameRealtimeRemoteUpdateListener::CameraSync() { IGame *pGame = gEnv->pGame; if(!pGame) return; IGameFramework *pGameFramework=pGame->GetIGameFramework(); if(!pGameFramework) return; IViewSystem *pViewSystem=pGameFramework->GetIViewSystem(); if(!pViewSystem) return; IView *pView=pViewSystem->GetActiveView(); if(!pView) return; IEntity *pEntity = gEnv->pEntitySystem->GetEntity(pView->GetLinkedId()); if(!pEntity) return; IActor *pPlayer=pGameFramework->GetClientActor(); if ( !pPlayer ) return; IEntity * pPlayerEntity = pPlayer->GetEntity(); if (!pPlayerEntity) return; IPhysicalEntity * piPlayerPhysics = pPlayerEntity->GetPhysics(); if ( !piPlayerPhysics ) return; pe_player_dimensions dim; piPlayerPhysics->GetParams( &dim ); //TODO: only GDCE2011, in the future make this game magic constant be gone in LiveCreate 2.0 // game player view code has a complex position code path, the sync position should be // honoured by game code when live creaate camera sync is enabled m_Position.z -= 1.62f; pEntity->SetPos(m_Position); pPlayerEntity->Hide(false); pViewSystem->SetOverrideCameraRotation(true,Quat::CreateRotationVDir(m_ViewDirection)); pPlayerEntity->Hide(true); SEntityUpdateContext ctx; pPlayer->Update( ctx, 0 ); m_bCameraSync = true; }
bool CCannonBall::RayTraceGeometry( const EventPhysCollision* pCollision, const Vec3& pos, const Vec3& hitDirection, SBackHitInfo* pBackHitInfo ) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); bool exitPointFound = false; IPhysicalEntity* pCollider = pCollision->pEntity[1]; assert(pCollider); pe_params_part partParams; partParams.partid = pCollision->partid[1]; pe_status_pos posStatus; if (pCollider->GetParams(&partParams) && pCollider->GetStatus(&posStatus)) { if (partParams.pPhysGeom && partParams.pPhysGeom->pGeom) { geom_world_data geomWorldData; geomWorldData.R = Matrix33(posStatus.q*partParams.q); geomWorldData.offset = posStatus.pos + (posStatus.q * partParams.pos); geomWorldData.scale = posStatus.scale * partParams.scale; geom_contact *pContacts; intersection_params intersectionParams; IGeometry* pRayGeometry = s_pRayWrapper->GetRay(pos, hitDirection); const Vec3 hitDirectionNormalized = hitDirection.GetNormalized(); { WriteLockCond lock; const int contactCount = partParams.pPhysGeom->pGeom->IntersectLocked(pRayGeometry,&geomWorldData,0,&intersectionParams,pContacts,lock); if (contactCount > 0) { float bestDistance = 10.0f; for (int i = (contactCount-1); (i >= 0) && (pContacts[i].t < bestDistance) && ((pContacts[i].n*hitDirectionNormalized) < 0); i--) { bestDistance = (float)pContacts[i].t; pBackHitInfo->pt = pContacts[i].pt; exitPointFound = true; } } } // lock } } s_pRayWrapper->ResetRay(); return exitPointFound; }
void CIntersectionAssistanceUnit::DebugUpdate() const { if(g_pGameCVars->pl_pickAndThrow.intersectionAssistDebugEnabled) { IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_subjectEntityId); if(pEntity) { IPhysicalEntity *pPhysical = pEntity->GetPhysics(); if(pPhysical) { const float fFontSize = 1.2f; float drawColor[4] = {1.0f, 1.0f, 1.0f, 1.0f}; string sMsg(string().Format(" Entity ID: [%d]", m_subjectEntityId)); sMsg += string().Format("\n Entity Name: [%s]", pEntity->GetName()); sMsg += string().Format("\n EmbedTimer: [%.3f]", m_embedTimer); sMsg += string().Format("\n EmbedState: [%s]",(m_embedState == eES_None) ? "NONE" : (m_embedState == eES_Evaluating) ? "EVALUATING" : (m_embedState == eES_ReEvaluating) ? "REEVALUATING" : (m_embedState == eES_NotEmbedded) ? "NOT EMBEDDED" : (m_embedState == eES_Embedded) ? "EMBEDDED" : "UNKNOWN"); Vec3 vCurrTrans = m_entityStartingWPos - pEntity->GetWorldPos(); sMsg += string().Format("\n Translation: < %.3f, %.3f, %.3f >", vCurrTrans.x, vCurrTrans.y, vCurrTrans.z ); sMsg += string().Format("\n Trans magnitude: < %.3f >", vCurrTrans.GetLength() ); sMsg += string().Format("\n Trans per sec: < %.3f >", vCurrTrans.GetLength() / g_pGameCVars->pl_pickAndThrow.intersectionAssistTimePeriod ); sMsg += string().Format("\n Collision count: %u", m_collisionCount ); // RENDER Vec3 vDrawPos = pEntity->GetWorldPos() + Vec3(0.0f,0.0f,0.6f); gEnv->pRenderer->DrawLabelEx(vDrawPos, fFontSize, drawColor, true, true, sMsg.c_str()); // Box pe_params_bbox bbox; if(pPhysical->GetParams(&bbox)) { ColorB colDefault = ColorB( 127,127,127 ); ColorB embedded = ColorB(255, 0, 0); ColorB notEmbedded = ColorB(0, 255, 0); gEnv->pRenderer->GetIRenderAuxGeom()->DrawAABB( AABB(bbox.BBox[0],bbox.BBox[1]), Matrix34(IDENTITY), false, (m_embedState == eES_Embedded) ? embedded : (m_embedState == eES_NotEmbedded) ? notEmbedded : colDefault, eBBD_Faceted); } } } } }
//------------------------------------------------------------------------ void CVehicleActionEntityAttachment::Update(const float deltaTime) { if(m_isAttached) return; IEntitySystem *pEntitySystem = gEnv->pEntitySystem; assert(pEntitySystem); IEntity *pEntity = pEntitySystem->GetEntity(m_entityId); if(!pEntity) return; IPhysicalEntity *pPhysEntity = pEntity->GetPhysics(); if(!pPhysEntity) return; pe_simulation_params paramsSim; float gravity; if(pPhysEntity->GetParams(¶msSim)) gravity = abs(paramsSim.gravity.z); else gravity = 9.82f; pe_status_dynamics dyn; if(pPhysEntity->GetStatus(&dyn)) { pe_action_impulse impulse; impulse.impulse = Matrix33(pEntity->GetWorldTM()) * Vec3(0.0f, 0.0f, 1.0f) * g_parachuteForce * gravity; impulse.impulse = impulse.impulse - dyn.v; impulse.impulse *= dyn.mass * deltaTime; impulse.iSource = 3; pPhysEntity->Action(&impulse); } m_timer -= deltaTime; if(m_timer <= 0.0f || dyn.v.z >= 0.0f) m_pVehicle->SetObjectUpdate(this, IVehicle::eVOU_NoUpdate); }
void CPlayerStateSwim::OnEnter( CPlayer& player ) { player.m_playerStateSwim_WaterTestProxy.OnEnterWater(player); IPhysicalEntity* pPhysEnt = player.GetEntity()->GetPhysics(); if (pPhysEnt != NULL) { // get current gravity before setting to zero. pe_player_dynamics simPar; if( pPhysEnt->GetParams(&simPar) != 0 ) { m_gravity = simPar.gravity; } CPlayerStateUtil::PhySetFly( player ); } m_lastWaterLevel = player.m_playerStateSwim_WaterTestProxy.GetWaterLevel(); m_lastWaterLevelTime = player.m_playerStateSwim_WaterTestProxy.GetWaterLevelTimeUpdated(); player.m_stats.inAir = 0.0f; if (player.IsClient()) { ICameraMode::AnimationSettings animationSettings; animationSettings.positionFactor = 1.0f; animationSettings.rotationFactor = GetSwimParams().m_stateSwim_animCameraFactor; player.GetPlayerCamera()->SetCameraModeWithAnimationBlendFactors( eCameraMode_PartialAnimationControlled, animationSettings, "Entering swim state" ); player.SendMusicLogicEvent(eMUSICLOGICEVENT_PLAYER_SWIM_ENTER); if (!player.IsCinematicFlagActive(SPlayerStats::eCinematicFlag_HolsterWeapon)) player.HolsterItem(true); if (gEnv->bMultiplayer) // any left hand holding in SP? { player.HideLeftHandObject(true); } } // Record 'Swim' telemetry stats. CStatsRecordingMgr::TryTrackEvent(&player, eGSE_Swim, true); }
void CPlayerStateFly::OnEnter( CPlayer& player ) { pe_player_dynamics simPar; IPhysicalEntity* piPhysics = player.GetEntity()->GetPhysics(); if (!piPhysics || piPhysics->GetParams(&simPar) == 0) { return; } player.m_actorPhysics.velocity = player.m_actorPhysics.velocityUnconstrained.Set(0,0,0); player.m_actorPhysics.speed = player.m_stats.speedFlat = 0.0f; player.m_actorPhysics.groundMaterialIdx = -1; player.m_actorPhysics.gravity = simPar.gravity; player.m_stats.fallSpeed = 0.0f; player.m_stats.inFiring = 0; CPlayerStateUtil::PhySetFly( player ); }
//------------------------------------------------------------------------ void CVehiclePartAnimated::FlagSkeleton(ISkeletonPose* pSkeletonPose,IDefaultSkeleton &rIDefaultSkeleton) { if (!pSkeletonPose) return; IPhysicalEntity* pPhysics = GetEntity()->GetPhysics(); if (!pPhysics) return; string name; int idWater = rIDefaultSkeleton.GetJointIDByName("proxy_water"); uint32 buoyancyParts = (idWater != -1) ? 1 : 0; uint32 jointCount = rIDefaultSkeleton.GetJointCount(); for (uint32 i = 0; i < jointCount; ++i) { int physId = pSkeletonPose->GetPhysIdOnJoint(i); if (physId >= 0) { CheckColltypeHeavy(physId); name = rIDefaultSkeleton.GetJointNameByID(i); // when water proxy available, remove float from all others // if no water proxy, we leave only "proxy" parts floating if (idWater != -1) { if (i == idWater) { SetFlags(physId, geom_collides, false); SetFlagsCollider(physId, 0); } else SetFlags(physId, geom_floats, false); } else { if (name.find("proxy") != string::npos) ++buoyancyParts; else SetFlags(physId, geom_floats, false); } // all objects which have a corresponding *_proxy on the skeleton // are set to ray collision only if (name.find("_proxy") == string::npos) { name.append("_proxy"); int proxyId = rIDefaultSkeleton.GetJointIDByName(name.c_str()); if (proxyId != -1) { // remove ray collision from hull proxy(s) SetFlags(pSkeletonPose->GetPhysIdOnJoint(proxyId), geom_colltype_ray | geom_colltype13, false); // get StatObj from main part, to connect proxies foreignData with it IStatObj* pStatObj = pSkeletonPose->GetStatObjOnJoint(i); if (pStatObj) { pe_params_part params; params.partid = proxyId; if (pPhysics->GetParams(¶ms)) { if (params.pPhysGeom && params.pPhysGeom->pGeom) params.pPhysGeom->pGeom->SetForeignData(pStatObj, 0); } } for (int p = 2; p < 6; ++p) { // check additional proxies, by naming convention _02, .. _05 char buf[64]; cry_sprintf(buf, "%s_%02i", name.c_str(), p); proxyId = rIDefaultSkeleton.GetJointIDByName(buf); if (proxyId == -1) break; int proxyPhysId = pSkeletonPose->GetPhysIdOnJoint(proxyId); if (proxyPhysId == -1) continue; SetFlags(proxyPhysId, geom_colltype_ray | geom_colltype13, false); // connect proxies to main StatObj (needed for bullet tests, decals) if (pStatObj) { pe_params_part params; params.partid = proxyPhysId; if (pPhysics->GetParams(¶ms)) { if (params.pPhysGeom && params.pPhysGeom->pGeom) params.pPhysGeom->pGeom->SetForeignData(pStatObj, 0); } } } // set ray-collision only on the part SetFlags(physId, geom_collides | geom_floats, false); SetFlags(physId, geom_colltype_ray | geom_colltype13, true); SetFlagsCollider(physId, 0); } } } } if (buoyancyParts == 0) { // as fallback, use part with largest volume for buoyancy int partId = -1; float maxV = 0.f; pe_status_nparts nparts; int numParts = pPhysics->GetStatus(&nparts); for (int i = 0; i < numParts; ++i) { pe_params_part params; params.ipart = i; if (pPhysics->GetParams(¶ms)) { float v = (params.pPhysGeomProxy) ? params.pPhysGeomProxy->V : params.pPhysGeom->V; if (v > maxV) { partId = params.partid; maxV = v; } } } if (partId != -1) SetFlags(partId, geom_floats, true); else GameWarning("[CVehiclePartAnimated]: <%s> has no buoyancy parts! (Check material for correct physicalization setup properties)",GetEntity()->GetName()); } int jointId, physId; if ((jointId = rIDefaultSkeleton.GetJointIDByName("proxy_skirt")) != -1) { if ((physId = pSkeletonPose->GetPhysIdOnJoint(jointId)) != -1) { SetFlags(physId, geom_collides | geom_floats, false); SetFlags(physId, geom_colltype_ray | geom_colltype13 | geom_colltype_player | geom_colltype_foliage, true); SetFlagsCollider(physId, 0); } } // remove collision flags from all _proxy geoms by debug cvar // useful for seeing through, testing ray proxies etc if (VehicleCVars().v_disable_hull > 0) { for (uint32 i = 0; i < rIDefaultSkeleton.GetJointCount(); ++i) { if (strstr(rIDefaultSkeleton.GetJointNameByID(i), "_proxy")) { SetFlags(pSkeletonPose->GetPhysIdOnJoint(i), geom_collides | geom_floats, false); SetFlagsCollider(pSkeletonPose->GetPhysIdOnJoint(i), 0); } } } }
void CVehicleDamageBehaviorBlowTire::DamagePlayers() { // check for the nasty case when the player is shooting at the vehicle tires while prone // under or behind the car, In that case the player should get killed by the vehicle, // otherwise he gets stuck forever. Note that he should only get killed when the tier // is actually destroyed and not by collision resulting by the impulse added by just // shooting at the tiers. Unfortunately using physics for doing this check is not reliable // enough so we have to check it explicitly IEntityPhysicalProxy *pPhysicsProxy = (IEntityPhysicalProxy*)m_pVehicle->GetEntity()->GetProxy(ENTITY_PROXY_PHYSICS); if (!pPhysicsProxy) return; AABB bbox; pPhysicsProxy->GetWorldBounds( bbox ); IPhysicalWorld *pWorld = gEnv->pSystem->GetIPhysicalWorld(); IPhysicalEntity **ppColliders; // check entities in collision with the car int cnt = pWorld->GetEntitiesInBox( bbox.min,bbox.max, ppColliders,ent_living); for (int i = 0; i < cnt; i++) { IEntity *pEntity = gEnv->pEntitySystem->GetEntityFromPhysics( ppColliders[i] ); if (!pEntity) continue; // skip the vehicle itself if (pEntity==m_pVehicle->GetEntity()) continue; IPhysicalEntity *pPhysEnt = pEntity->GetPhysics(); if (!pPhysEnt) continue; IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId()); if(!pActor) continue; //Jan M.: the player is killed when he entered the vehicle while prone although he is still passenger! if(m_pVehicle == pActor->GetLinkedVehicle()) continue; //the player must be prone under the vehicle IAnimatedCharacter * animatedCharacter=pActor->GetAnimatedCharacter(); if (!animatedCharacter) continue; int stance = animatedCharacter->GetCurrentStance(); if (stance!=STANCE_PRONE) continue; pe_player_dimensions dim; if (!pPhysEnt->GetParams(&dim)) continue; // position returned is at entity's feet, add head position from physics Vec3 vPos1=pEntity->GetPos(); vPos1.z = vPos1.z + dim.heightHead; float fZ=bbox.GetCenter().z; if (vPos1.z>fZ) continue; // not under the vehicle // at this point we have a collision with the car moving down and the guy prone under the car, it is safe // to assume he has been squished so let's kill him. if (gEnv->bServer && pActor->GetHealth()>0) { // adding a server hit to make it working in MP IGameRules *pGameRules = gEnv->pGame->GetIGameFramework()->GetIGameRulesSystem()->GetCurrentGameRules(); if (pGameRules) { HitInfo hit; EntityId shooterId=m_pVehicle->GetEntityId(); if (m_pVehicle->GetDriver()) shooterId=m_pVehicle->GetDriver()->GetEntityId(); hit.targetId = pEntity->GetId(); hit.shooterId = shooterId; hit.weaponId = m_pVehicle->GetEntityId(); hit.damage = 1000.f; hit.type = 0; hit.pos = pActor->GetEntity()->GetWorldPos(); pGameRules->ServerHit(hit); } } } //i }
//------------------------------------------------------------------------ int CScriptBind_Actor::GetCloseColliderParts(IFunctionHandler *pH, int characterSlot, Vec3 hitPos, float radius) { // find nearest physic. parts to explosion center // for now we just return the closest part (using the AABB) CActor *pActor = GetActor(pH); if (!pActor) return pH->EndFunction(); IEntity* pEntity = pActor->GetEntity(); ICharacterInstance* pChar = pEntity->GetCharacter(characterSlot); if (pChar && pChar->GetISkeletonPose()->GetCharacterPhysics()) { IPhysicalEntity* pPhysics = pChar->GetISkeletonPose()->GetCharacterPhysics(); pe_status_nparts nparts; int numParts = pPhysics->GetStatus(&nparts); float minLenSq = radius*radius + 0.1f; int minLenPart = -1; pe_status_pos status; for (int i=0; i<numParts; ++i) { status.ipart = i; if (pPhysics->GetStatus(&status)) { AABB box(status.pos+status.BBox[0], status.pos+status.BBox[1]); // if hitpos inside AABB, return if (box.IsContainPoint(hitPos)) { minLenPart = i; break; } // else find closest distance float lenSq = Distance::Point_AABBSq(hitPos, box); if (lenSq < minLenSq) { minLenSq = lenSq; minLenPart = i; } } } // get material from selected part static ISurfaceTypeManager* pSurfaceMan = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager(); if (minLenPart != -1) { pe_params_part params; params.ipart = minLenPart; if (pPhysics->GetParams(¶ms)) { phys_geometry* pGeom = params.pPhysGeomProxy ? params.pPhysGeomProxy : params.pPhysGeom; if (pGeom->surface_idx > 0 && pGeom->surface_idx < params.nMats) { if (ISurfaceType *pSurfaceType=pSurfaceMan->GetSurfaceType(pGeom->pMatMapping[pGeom->surface_idx])) return pH->EndFunction(params.partid, pSurfaceType->GetName(), pSurfaceType->GetType()); } } return pH->EndFunction(params.partid); } } return pH->EndFunction(); }
void CPlayerStateUtil::UpdatePlayerPhysicsStats( CPlayer& player, SActorPhysics& actorPhysics, float frameTime ) { const int currentFrameID = gEnv->pRenderer->GetFrameID(); if( actorPhysics.lastFrameUpdate < currentFrameID ) { pe_status_living livStat; if( !CPlayerStateUtil::GetPhysicsLivingStat( player, &livStat ) ) { return; } SPlayerStats& stats = *player.GetActorStats(); const Vec3 newVelocity = livStat.vel-livStat.velGround; actorPhysics.velocityDelta = newVelocity - actorPhysics.velocity; actorPhysics.velocity = newVelocity; actorPhysics.velocityUnconstrainedLast = actorPhysics.velocityUnconstrained; actorPhysics.velocityUnconstrained = livStat.velUnconstrained; actorPhysics.flags.SetFlags( SActorPhysics::EActorPhysicsFlags_WasFlying, actorPhysics.flags.AreAnyFlagsActive(SActorPhysics::EActorPhysicsFlags_Flying) ); actorPhysics.flags.SetFlags( SActorPhysics::EActorPhysicsFlags_Flying, livStat.bFlying > 0 ); actorPhysics.flags.SetFlags( SActorPhysics::EActorPhysicsFlags_Stuck, livStat.bStuck > 0 ); Vec3 flatVel(player.m_pPlayerRotation->GetBaseQuat().GetInverted()*newVelocity); flatVel.z = 0; stats.speedFlat = flatVel.len(); if(player.IsInAir()) { stats.maxAirSpeed = max(stats.maxAirSpeed, newVelocity.GetLengthFast()); } else { stats.maxAirSpeed = 0.f; } float fSpeedFlatSelector = stats.speedFlat - 0.1f; const float groundNormalBlend = clamp(frameTime * 6.666f, 0.0f, 1.0f); actorPhysics.groundNormal = LERP(actorPhysics.groundNormal, livStat.groundSlope, groundNormalBlend); if (livStat.groundSurfaceIdxAux > 0) actorPhysics.groundMaterialIdx = livStat.groundSurfaceIdxAux; else actorPhysics.groundMaterialIdx = livStat.groundSurfaceIdx; actorPhysics.groundHeight = livStat.groundHeight; EntityId newGroundColliderId = 0; if (livStat.pGroundCollider) { IEntity* pEntity = gEnv->pEntitySystem->GetEntityFromPhysics(livStat.pGroundCollider); newGroundColliderId = pEntity ? pEntity->GetId() : 0; } if( newGroundColliderId != actorPhysics.groundColliderId ) { if( actorPhysics.groundColliderId ) { if( IGameObject* pGameObject = gEnv->pGame->GetIGameFramework()->GetGameObject( actorPhysics.groundColliderId ) ) { SGameObjectEvent event( eGFE_StoodOnChange, eGOEF_ToExtensions ); event.ptr = &player; event.paramAsBool = false; pGameObject->SendEvent(event); } } if( newGroundColliderId ) { if( IGameObject* pGameObject = gEnv->pGame->GetIGameFramework()->GetGameObject( newGroundColliderId ) ) { SGameObjectEvent event( eGFE_StoodOnChange, eGOEF_ToExtensions ); event.ptr = &player; event.paramAsBool = true; pGameObject->SendEvent(event); } } actorPhysics.groundColliderId = newGroundColliderId; } IPhysicalEntity *pPhysEnt = player.GetEntity()->GetPhysics(); if( pPhysEnt ) { pe_status_dynamics dynStat; pPhysEnt->GetStatus(&dynStat); actorPhysics.angVelocity = dynStat.w; actorPhysics.mass = dynStat.mass; pe_player_dynamics simPar; if (pPhysEnt->GetParams(&simPar) != 0) { actorPhysics.gravity = simPar.gravity; } } actorPhysics.lastFrameUpdate = currentFrameID; #ifdef PLAYER_MOVEMENT_DEBUG_ENABLED player.GetMovementDebug().DebugGraph_AddValue("PhysVelo", livStat.vel.GetLength()); player.GetMovementDebug().DebugGraph_AddValue("PhysVeloX", livStat.vel.x); player.GetMovementDebug().DebugGraph_AddValue("PhysVeloY", livStat.vel.y); player.GetMovementDebug().DebugGraph_AddValue("PhysVeloZ", livStat.vel.z); player.GetMovementDebug().DebugGraph_AddValue("PhysVeloUn", livStat.velUnconstrained.GetLength()); player.GetMovementDebug().DebugGraph_AddValue("PhysVeloUnX", livStat.velUnconstrained.x); player.GetMovementDebug().DebugGraph_AddValue("PhysVeloUnY", livStat.velUnconstrained.y); player.GetMovementDebug().DebugGraph_AddValue("PhysVeloUnZ", livStat.velUnconstrained.z); player.GetMovementDebug().DebugGraph_AddValue("PhysVelReq", livStat.velRequested.GetLength()); player.GetMovementDebug().DebugGraph_AddValue("PhysVelReqX", livStat.velRequested.x); player.GetMovementDebug().DebugGraph_AddValue("PhysVelReqY", livStat.velRequested.y); player.GetMovementDebug().DebugGraph_AddValue("PhysVelReqZ", livStat.velRequested.z); player.GetMovementDebug().LogVelocityStats(player.GetEntity(), livStat, stats.downwardsImpactVelocity, stats.fallSpeed); #endif } }
//----------------------------------------------- //This function is only executed on the server void CC4Projectile::Stick(EventPhysCollision *pCollision) { assert(pCollision); int trgId = 1; IPhysicalEntity *pTarget = pCollision->pEntity[trgId]; if(pTarget == GetEntity()->GetPhysics()) { trgId = 0; pTarget = pCollision->pEntity[trgId]; } //Do not stick to breakable glass if(ISurfaceType *pSurfaceType = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceType(pCollision->idmat[trgId])) { if(pSurfaceType->GetBreakability()==1) { m_notStick = true; return; } } IEntity *pTargetEntity = pTarget ? gEnv->pEntitySystem->GetEntityFromPhysics(pTarget) : 0; if(pTarget && (!pTargetEntity || (pTargetEntity->GetId() != m_ownerId))) { //Special cases if(pTargetEntity) { //Stick to actors using a character attachment CActor *pActor = static_cast<CActor *>(gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pTargetEntity->GetId())); //Not in MP if(pActor && gEnv->bMultiplayer) { m_notStick = true; return; } if(pActor && pActor->GetHealth()>0) { if(pActor->GetActorSpecies()!=eGCT_HUMAN) { m_notStick = true; return; } if(StickToCharacter(true,pTargetEntity)) { GetGameObject()->SetAspectProfile(eEA_Physics, ePT_None); m_stuck = true; } m_notStick = true; return; } //Do not stick to small objects... if(!pActor) { pe_params_part pPart; pPart.ipart = 0; if(pTarget->GetParams(&pPart) && pPart.pPhysGeom && pPart.pPhysGeom->V<0.15f) { m_notStick = true; return; } } } else if(pTarget->GetType()==PE_LIVING) { m_notStick = true; return; } if(!pTargetEntity) StickToStaticObject(pCollision,pTarget); else { //Do not attach to items if(g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(pTargetEntity->GetId())) { m_notStick = true; return; } Matrix34 mat = pTargetEntity->GetWorldTM(); mat.Invert(); Vec3 pos = mat.TransformPoint(pCollision->pt); mat.SetIdentity(); mat.SetRotation33(Matrix33::CreateOrientation(-pCollision->n,GetEntity()->GetWorldTM().TransformVector(Vec3(0,0,1)),gf_PI)); mat.SetTranslation(pos); //Dephysicalize and stick GetGameObject()->SetAspectProfile(eEA_Physics, ePT_None); StickToEntity(pTargetEntity,mat); if(gEnv->bMultiplayer) { Quat rot(Matrix33::CreateOrientation(-pCollision->n,GetEntity()->GetWorldTM().TransformVector(Vec3(0,0,1)),gf_PI*0.5f)); GetGameObject()->InvokeRMI(CC4Projectile::ClStickToEntity(),ProjectileStickToEntity(pTargetEntity->GetId(),pos,rot),eRMI_ToAllClients); } } m_stuck = true; } }
//------------------------------------------------------------------------ void CVehicleMovementVTOL::ProcessActions(const float deltaTime) { FUNCTION_PROFILER( GetISystem(), PROFILE_GAME ); UpdateDamages(deltaTime); UpdateEngine(deltaTime); m_velDamp = 0.25f; m_playerControls.ProcessActions(deltaTime); Limit(m_forwardAction, -1.0f, 1.0f); Limit(m_strafeAction, -1.0f, 1.0f); m_actionYaw = 0.0f; Vec3 worldPos = m_pEntity->GetWorldPos(); IPhysicalEntity* pPhysics = GetPhysics(); // get the current state // roll pitch + yaw Matrix34 worldTM = m_pRotorPart ? m_pRotorPart->GetWorldTM() : m_pEntity->GetWorldTM(); // if (m_pRotorPart) // worldTM = m_pRotorPart->GetWorldTM(); // else // worldTM = m_pEntity->GetWorldTM(); Vec3 specialPos = worldTM.GetTranslation(); Ang3 angles = Ang3::GetAnglesXYZ(Matrix33(worldTM)); Matrix33 tm; tm.SetRotationXYZ((angles)); // +ve pitch means nose up const float& currentPitch = angles.x; // +ve roll means to the left const float& currentRoll = angles.y; // +ve direction mean rotation anti-clockwise about the z axis - 0 means along y float currentDir = angles.z; const float maxPitchAngle = 60.0f; float pitchDeg = RAD2DEG(currentPitch); if (pitchDeg >= (maxPitchAngle * 0.75f)) { float mult = pitchDeg / (maxPitchAngle); if (mult > 1.0f && m_desiredPitch < 0.0f) { m_desiredPitch *= 0.0f; m_actionPitch *= 0.0f; m_desiredPitch += 0.2f * mult; } else if (m_desiredPitch < 0.0f) { m_desiredPitch *= (1.0f - mult); m_desiredPitch += 0.05f; } } else if (pitchDeg <= (-maxPitchAngle * 0.75f)) { float mult = abs(pitchDeg) / (maxPitchAngle); if (mult > 1.0f && m_desiredPitch > 0.0f) { m_desiredPitch *= 0.0f; m_actionPitch *= 0.0f; m_desiredPitch += 0.2f * mult; } else if (m_desiredPitch > 0.0f) { m_desiredPitch *= (1.0f - mult); m_desiredPitch -= 0.05f; } } if (currentRoll >= DEG2RAD(m_maxRollAngle * 0.7f) && m_desiredRoll > 0.001f) { float r = currentRoll / DEG2RAD(m_maxRollAngle); r = min(1.0f, r * 1.0f); r = 1.0f - r; m_desiredRoll *= r; m_desiredRoll = min(1.0f, m_desiredRoll); } else if (currentRoll <= DEG2RAD(-m_maxRollAngle * 0.7f) && m_desiredRoll < 0.001f) { float r = abs(currentRoll) / DEG2RAD(m_maxRollAngle); r = min(1.0f, r * 1.0f); r = 1.0f - r; m_desiredRoll *= r; m_desiredRoll = max(-1.0f, m_desiredRoll); } Vec3 currentFwdDir2D = m_currentFwdDir; currentFwdDir2D.z = 0.0f; currentFwdDir2D.NormalizeSafe(); Vec3 currentLeftDir2D(-currentFwdDir2D.y, currentFwdDir2D.x, 0.0f); Vec3 currentVel = m_PhysDyn.v; Vec3 currentVel2D = currentVel; currentVel2D.z = 0.0f; float currentHeight = worldPos.z; float currentFwdSpeed = currentVel.Dot(currentFwdDir2D); ProcessActions_AdjustActions(deltaTime); float inputMult = m_basicSpeedFraction; // desired things float turnDecreaseScale = m_yawDecreaseWithSpeed / (m_yawDecreaseWithSpeed + fabs(currentFwdSpeed)); Vec3 desired_vel2D = currentFwdDir2D * m_forwardAction * m_maxFwdSpeed * inputMult + currentLeftDir2D * m_strafeAction * m_maxLeftSpeed * inputMult; // calculate the angle changes Vec3 desiredVelChange2D = desired_vel2D - currentVel2D; float desiredTiltAngle = m_tiltPerVelDifference * desiredVelChange2D.GetLength(); Limit(desiredTiltAngle, -m_maxTiltAngle, m_maxTiltAngle); float goal = abs(m_desiredPitch) + abs(m_desiredRoll); goal *= 1.5f; Interpolate(m_playerAcceleration, goal, 0.25f, deltaTime); Limit(m_playerAcceleration, 0.0f, 5.0f); //static float g_angleLift = 4.0f; if (abs(m_liftAction) > 0.001f && abs(m_forwardAction) < 0.001) { // float pitch = RAD2DEG(currentPitch); if (m_liftPitchAngle < 0.0f && m_liftAction > 0.0f) m_liftPitchAngle = 0.0f; else if (m_liftPitchAngle > 0.0f && m_liftAction < 0.0f) m_liftPitchAngle = 0.0f; Interpolate(m_liftPitchAngle, 1.25f * m_liftAction, 0.75f, deltaTime); if (m_liftPitchAngle < 1.0f && m_liftPitchAngle > -1.0f) m_desiredPitch += 0.05f * m_liftAction; } else if (m_liftAction < 0.001f && abs(m_liftPitchAngle) > 0.001) { Interpolate(m_liftPitchAngle, 0.0f, 1.0f, deltaTime); m_desiredPitch += 0.05f * -m_liftPitchAngle; } /* todo else if (m_liftAction < -0.001f) { m_desiredPitch += min(0.0f, (DEG2RAD(-5.0f) - currentPitch)) * 0.5f * m_liftAction; }*/ if (!iszero(m_desiredPitch)) { m_actionPitch -= m_desiredPitch * m_pitchInputConst; Limit(m_actionPitch, -m_maxYawRate, m_maxYawRate); } float rollAccel = 1.0f; if (abs(currentRoll + m_desiredRoll) < abs(currentRoll)) rollAccel *= 1.25f; m_actionRoll += m_pitchActionPerTilt * m_desiredRoll * rollAccel * (m_playerAcceleration + 1.0f); Limit(m_actionRoll, -10.0f, 10.0f); Limit(m_actionPitch, -10.0f, 10.0f); // roll as we turn if (!m_strafeAction) { m_actionYaw += m_yawPerRoll * currentRoll; } if (abs(m_strafeAction) > 0.001f) { float side = 0.0f; side = min(1.0f, max(-1.0f, m_strafeAction)); float roll = DEG2RAD(m_extraRollForTurn * 0.25f * side) - (currentRoll); m_actionRoll += max(0.0f, abs(roll)) * side * 1.0f; } float relaxRollTolerance = 0.0f; if (abs(m_turnAction) > 0.01f || abs(m_PhysDyn.w.z) > DEG2RAD(3.0f)) { m_actionYaw += -m_turnAction * m_yawInputConst * GetDamageMult(); float side = 0.0f; if (abs(m_turnAction) > 0.01f) side = min(1.0f, max(-1.0f, m_turnAction)); float roll = DEG2RAD(m_extraRollForTurn * side) - (currentRoll); m_actionRoll += max(0.0f, abs(roll)) * side * m_rollForTurnForce; roll *= max(1.0f, abs(m_PhysDyn.w.z)); m_actionRoll += roll; Limit(m_actionYaw, -m_maxYawRate, m_maxYawRate); } m_desiredDir = currentDir; m_lastDir = currentDir; float boost = Boosting() ? m_boostMult : 1.0f; float liftActionMax = 1.0f; if (m_pAltitudeLimitVar) { float altitudeLimit = m_pAltitudeLimitVar->GetFVal(); if (!iszero(altitudeLimit)) { float altitudeLowerOffset; if (m_pAltitudeLimitLowerOffsetVar) { float r = 1.0f - min(1.0f, max(0.0f, m_pAltitudeLimitLowerOffsetVar->GetFVal())); altitudeLowerOffset = r * altitudeLimit; } else altitudeLowerOffset = altitudeLimit; float mult = 1.0f; if (currentHeight >= altitudeLimit) { if (m_liftAction > 0.f) { mult = 0.0f; } } else if (currentHeight >= altitudeLowerOffset) { float zone = altitudeLimit - altitudeLowerOffset; mult = (altitudeLimit - currentHeight) / (zone); } m_liftAction *= mult; if (currentPitch > DEG2RAD(0.0f)) { if (m_forwardAction > 0.0f) m_forwardAction *= mult; if (m_actionPitch > 0.0f) { m_actionPitch *= mult; m_actionPitch += -currentPitch; } } m_desiredHeight = min(altitudeLowerOffset, currentHeight); } } else { m_desiredHeight = currentHeight; } if (abs(m_liftAction) > 0.001f) { m_liftAction = min(liftActionMax, max(-0.2f, m_liftAction)); m_hoveringPower = (m_powerInputConst * m_liftAction) * boost; m_noHoveringTimer = 0.0f; } else if (!m_isTouchingGround) { if (m_noHoveringTimer <= 0.0f) { float gravity; pe_simulation_params paramsSim; if (pPhysics->GetParams(¶msSim)) gravity = abs(paramsSim.gravity.z); else gravity = 9.2f; float upDirZ = m_workingUpDir.z; if (abs(m_forwardAction) > 0.01 && upDirZ > 0.0f) upDirZ = 1.0f; else if (upDirZ > 0.8f) upDirZ = 1.0f; float upPower = upDirZ; upPower -= min(1.0f, abs(m_forwardAction) * abs(angles.x)); float turbulenceMult = 1.0f - min(m_turbulenceMultMax, m_turbulence); Vec3& impulse = m_control.impulse; impulse += Vec3(0.0f, 0.0f, upPower) * gravity * turbulenceMult * GetDamageMult(); impulse.z -= m_PhysDyn.v.z * turbulenceMult; } else { m_noHoveringTimer -= deltaTime; } } if (m_pStabilizeVTOL) { float stabilizeTime = m_pStabilizeVTOL->GetFVal(); if (stabilizeTime > 0.0f) { if (m_relaxTimer < 6.0f) m_relaxTimer += deltaTime; else { float r = currentRoll - relaxRollTolerance; r = min(1.0f, max(-1.0f, r)); m_actionRoll += -r * m_relaxForce * (m_relaxTimer / 6.0f); } } } if (m_netActionSync.PublishActions( CNetworkMovementHelicopter(this) )) m_pVehicle->GetGameObject()->ChangedNetworkState(eEA_GameClientDynamic); }
//------------------------------------------------------------------------ void CVehicleMovementVTOL::PreProcessMovement(const float deltaTime) { CVehicleMovementHelicopter::PreProcessMovement(deltaTime); if (abs(m_forwardAction) > 0.0f && m_timeOnTheGround <= 0.01f) SetHorizontalMode(1.0f); else SetHorizontalMode(0.0f); if (m_forwardAction > 0.0f && m_timeOnTheGround <= 0.01f) { m_wingsTimer += deltaTime; m_wingsTimer = min(m_wingsTimer, m_timeUntilWingsRotate); } else { m_wingsTimer -= deltaTime * 0.65f; m_wingsTimer = max(m_wingsTimer, 0.0f); } Interpolate(m_wingsAnimTime, 1.0f - (m_wingsTimer / m_timeUntilWingsRotate), m_wingsSpeed, deltaTime); if (!m_isVTOLMovement) return; IPhysicalEntity* pPhysics = GetPhysics(); assert(pPhysics); float gravity; pe_simulation_params paramsSim; if (pPhysics->GetParams(¶msSim)) gravity = abs(paramsSim.gravity.z); else gravity = 9.2f; float vertical = 1.0f - m_horizontal; //m_engineForce = max(1.0f, gravity * vertical) * m_enginePower * max(0.25f, vertical); m_engineForce = 0.0f; m_engineForce += gravity * vertical * m_enginePower; m_engineForce += m_horizontal * m_enginePower; Matrix33 tm( m_PhysPos.q); Ang3 angles = Ang3::GetAnglesXYZ(tm); m_workingUpDir = m_engineUpDir; //Vec3(0.0f, 0.0f, 1.0f); m_workingUpDir += (vertical * m_rotorDiskTiltScale * Vec3(angles.y, -angles.x, 0.0f)); m_workingUpDir += (m_horizontal * m_rotorDiskTiltScale * Vec3(0.0f, 0.0f, angles.z)); m_workingUpDir = tm * m_workingUpDir; m_workingUpDir.z += 0.25f; m_workingUpDir.NormalizeSafe(); float strafe = m_strafeAction * m_strafeForce; if (m_noHoveringTimer <= 0.0f) { Vec3 forwardImpulse; float turbulenceMult = 1.0f - min(m_turbulenceMultMax, m_turbulence); forwardImpulse = m_currentFwdDir * m_enginePower * m_horizFwdForce * m_horizontal * (m_forwardAction + (Boosting() * m_boostForce)) * GetDamageMult() * turbulenceMult; if (m_forwardAction < 0.0f) forwardImpulse *= m_forwardInverseMult; forwardImpulse += m_currentUpDir * m_liftAction * m_enginePower * gravity; Vec3 fakeLeftDir = tm * Vec3(-1.0f, 0.0f, 0.0f); fakeLeftDir.z = 0.0f; forwardImpulse += fakeLeftDir * -strafe * m_enginePower * m_horizLeftForce * turbulenceMult; float horizDamp = 0.25f; static float vertDamp = 0.0f; if ( m_movementAction.isAI ) horizDamp *= abs(m_turnAction * 4.0f) + 1.0f; else horizDamp = m_velDamp; m_control.impulse += forwardImpulse; m_control.impulse.x -= m_PhysDyn.v.x * horizDamp * turbulenceMult; m_control.impulse.y -= m_PhysDyn.v.y * horizDamp * turbulenceMult; m_control.impulse.z -= m_PhysDyn.v.z * vertDamp * turbulenceMult; } m_workingUpDir.z += 0.45f * m_liftAction; m_workingUpDir.NormalizeSafe(); return; }
void CGameRealtimeRemoteUpdateListener::CameraSync() { IGame *pGame = gEnv->pGame; if(!pGame) return; IGameFramework *pGameFramework=pGame->GetIGameFramework(); if(!pGameFramework) return; IViewSystem *pViewSystem=pGameFramework->GetIViewSystem(); if(!pViewSystem) return; IView *pView=pViewSystem->GetActiveView(); if(!pView) return; IEntity *pEntity = gEnv->pEntitySystem->GetEntity(pView->GetLinkedId()); if(!pEntity) return; CPlayer *pPlayer=static_cast<CPlayer *>(pGameFramework->GetClientActor()); if ( !pPlayer ) return; IEntity * pPlayerEntity = pPlayer->GetEntity(); if (!pPlayerEntity) return; IPhysicalEntity * piPlayerPhysics = pPlayerEntity->GetPhysics(); if ( !piPlayerPhysics ) return; pe_player_dimensions dim; piPlayerPhysics->GetParams( &dim ); // if delta from head to center of character is zero, then we need to recompute it if( m_headPositionDelta.GetLength() == 0 ) { Vec3 camPos = pViewSystem->GetActiveView()->GetCurrentParams()->position; const Vec3& entPos = pEntity->GetPos(); m_headPositionDelta = camPos - entPos; } // offset the camera position by the current delta to put the head eye position to center of character m_Position -= m_headPositionDelta; pPlayerEntity->Hide(false); pEntity->SetPos(m_Position); pViewSystem->SetOverrideCameraRotation(true,Quat::CreateRotationVDir(m_ViewDirection)); #ifndef _RELEASE if ( m_bCameraSync == false && m_nPreviousFlyMode != eCameraModes_fly_mode_noclip ) { m_nPreviousFlyMode=pPlayer->GetFlyMode(); pPlayer->SetFlyMode(eCameraModes_fly_mode_noclip); } #endif pPlayerEntity->Hide(true); m_bCameraSync = true; }
//------------------------------------------------------------------------ void CVehiclePartAnimated::SetDrivingProxy(bool bDrive) { IVehicleMovement* pMovement = m_pVehicle->GetMovement(); if (!(pMovement && pMovement->UseDrivingProxy())) return; if (0 == m_hullMatId[bDrive]) // 0 means, nothin to do return; if (!m_pCharInstance) return; ISkeletonPose* pSkeletonPose = m_pCharInstance->GetISkeletonPose(); if (!pSkeletonPose) return; IDefaultSkeleton &rIDefaultSkeleton = m_pCharInstance->GetIDefaultSkeleton(); IPhysicalEntity* pPhysics = m_pVehicle->GetEntity()->GetPhysics(); if (!pPhysics) return; int id = rIDefaultSkeleton.GetJointIDByName("hull_proxy"); if (id < 0) { m_hullMatId[0] = m_hullMatId[1] = 0; return; } int partid = pSkeletonPose->GetPhysIdOnJoint(id); if (partid == -1) return; pe_params_part params; params.partid = partid; params.ipart = -1; if (!pPhysics->GetParams(¶ms) || !params.nMats) return; phys_geometry* pGeom = params.pPhysGeom; if (pGeom && pGeom->surface_idx < pGeom->nMats) { ISurfaceTypeManager* pSurfaceMan = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager(); // initialize once if (m_hullMatId[0] < 0) { int idDriving = 0; int idOrig = pGeom->pMatMapping[pGeom->surface_idx]; const char* matOrig = pSurfaceMan->GetSurfaceType(idOrig)->GetName(); if (strstr(matOrig, "mat_metal")) idDriving = pSurfaceMan->GetSurfaceTypeByName("mat_metal_nofric")->GetId(); else { string mat(matOrig); mat.append("_nofric"); idDriving = pSurfaceMan->GetSurfaceTypeByName(mat.c_str(), NULL, false)->GetId(); } //if (pDebug->GetIVal()) //CryLog("%s looking up driving surface replacement for %s (id %i) -> got id %i", m_pVehicle->GetEntity()->GetName(), matOrig, idOrig, idDriving); if (idDriving > 0) { // store old and new id m_hullMatId[0] = idOrig; m_hullMatId[1] = idDriving; /*if (pDebug->GetIVal()) { const char* matDriving = pSurfaceMan->GetSurfaceType(idDriving)->GetName(); CryLog("%s storing hull matId for swapping: %i (%s) -> %i (%s)", m_pVehicle->GetEntity()->GetName(), m_hullMatId[0], matOrig, m_hullMatId[1], matDriving); }*/ } else m_hullMatId[0] = m_hullMatId[1] = 0; } // only swap if materials available if (m_hullMatId[bDrive] > 0) { #if ENABLE_VEHICLE_DEBUG if (VehicleCVars().v_debugdraw == eVDB_Parts) CryLog("%s swapping hull proxy from %i (%s) to matId %i (%s)", m_pVehicle->GetEntity()->GetName(), m_hullMatId[bDrive ^ 1], pSurfaceMan->GetSurfaceType(m_hullMatId[bDrive ^ 1])->GetName(), m_hullMatId[bDrive], pSurfaceMan->GetSurfaceType(m_hullMatId[bDrive])->GetName()); #endif for (int n = 0; n < pGeom->nMats; ++n) { pGeom->pMatMapping[n] = m_hullMatId[bDrive]; } } } }
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 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); }