static void GetTalosInput(CPlayerRotation * pPlayerRotation, const CPlayer& rPlayer, float& x, float& z, const Vec3 playerView[4], float fFrameTime) { //Do I need to reproject the view to actually get the positioning correct? Shouldn't be. const Vec3 playerFwd = playerView[1]; const Vec3 playerRgt = playerView[0]; const Vec3 playerUp = playerView[2]; const Vec3 playerViewPos = playerView[3]; Vec3 playerPos = playerViewPos; IPhysicalEntity * pPhysicalEntity = rPlayer.GetEntity()->GetPhysics(); if(pPhysicalEntity) { pe_status_dynamics dyn_status; pPhysicalEntity->GetStatus(&dyn_status); playerPos = playerViewPos + (dyn_status.v * fFrameTime * 2.0f); } Vec3 follow_target_dir(ZERO); EntityId follow_target_id = 0; static EntityId s_follow_target_id = 0; CGameRules * pGameRules = g_pGame->GetGameRules(); int playerTeam = pGameRules->GetTeam(rPlayer.GetEntity()->GetId()); float cloakedPlayerMultiplier = g_pGameCVars->pl_aim_cloaked_multiplier; const bool multipleTeams = pGameRules->GetTeamCount() > 0; const TAutoaimTargets& aaTargets = g_pGame->GetAutoAimManager().GetAutoAimTargets(); const int targetCount = aaTargets.size(); float fBestTargetDistance = FLT_MAX; for (int i = 0; i < targetCount; ++i) { const SAutoaimTarget& target = aaTargets[i]; if(multipleTeams && (pGameRules->GetTeam(target.entityId) == playerTeam)) { continue; } Vec3 targetPos = target.secondaryAimPosition; IEntity * pEntity = gEnv->pEntitySystem->GetEntity(target.entityId); if(pEntity) { IPhysicalEntity * pPhysicalEntity2 = pEntity->GetPhysics(); if(pPhysicalEntity2) { pe_status_dynamics dyn_status; pPhysicalEntity2->GetStatus(&dyn_status); targetPos = targetPos + (dyn_status.v * fFrameTime); } } Vec3 targetDistVec = (targetPos - playerPos); float distance = targetDistVec.GetLength(); if (distance <= 0.01f) continue; Vec3 dirToTarget = targetDistVec / distance; // fast reject everything behind player, too far away or too near from line of view // sort rest by angle to crosshair and distance from player const int kAutoaimVisibilityLatency = 1; if (!g_pGame->GetPlayerVisTable()->CanLocalPlayerSee(target.entityId, kAutoaimVisibilityLatency)) { // Since both player and target entities are ignored, and the ray still intersected something, there's something in the way. // Need to profile this and see if it's faster to do the below checks before doing the linetest. It's fairly expensive but // linetests generally are as well... - Richard continue; } const float angleDot = dirToTarget.dot(-playerRgt); const float angle = (RAD2DEG(acos_tpl(angleDot)) - 90.f); const float absAngle = fabsf(angle); const float angleDotV = playerUp.dot(dirToTarget); const float angleToTargetV = (RAD2DEG(acos_tpl(angleDotV)) - 90.f); const float absAngleV = fabsf(angleToTargetV); if ( s_follow_target_id == target.entityId ) { follow_target_id = target.entityId; follow_target_dir = dirToTarget; break; } else if(distance < fBestTargetDistance) { fBestTargetDistance = distance; follow_target_id = target.entityId; follow_target_dir = dirToTarget; } } if(follow_target_id != 0) { //Player up is the normal of the plane that we are rotating around - (Correct? Or do we want to project both the player direction and the target direction onto the X/Y plane?) Vec3 vProjectedTargetHorz = playerUp.cross(follow_target_dir.cross(playerUp)); Vec3 vProjectedTargetVert = playerRgt.cross(follow_target_dir.cross(playerRgt)); float horzDot = vProjectedTargetHorz.GetNormalized().dot(playerFwd); float vertDot = vProjectedTargetVert.GetNormalized().dot(playerFwd); const float directionDotHorz = follow_target_dir.dot(playerRgt); const float directionDotVert = follow_target_dir.dot(playerUp); const float angle = acos_tpl(horzDot); const float angleToTargetV = acos_tpl(vertDot); const float fHorzFinalAngle = (float)__fsel(directionDotHorz, -angle, angle); const float fVertFinalAngle = (float)__fsel(directionDotVert, angleToTargetV, -angleToTargetV); //CryWatch("Angle to target: %.6f", RAD2DEG(angle)); //CryWatch("Final Angle to target: %.6f", RAD2DEG(fHorzFinalAngle)); x = x + fVertFinalAngle; z = z + fHorzFinalAngle; } s_follow_target_id = follow_target_id; return; }
void CSmokeManager::CullOtherSmokeEffectsInProximityWhenGrenadeHasLanded(SSmokeInstance& smokeInstance, IEntity* pGrenade) { if(pGrenade && (smokeInstance.state == eSIS_Active_PhysicsAwake)) { IPhysicalEntity* pPhysEnt = pGrenade->GetPhysics(); if(pPhysEnt) { pe_status_awake psa; if(pPhysEnt->GetStatus(&psa) == false) { // Was awake, now asleep... SSmokeInstance* pOldestSmokeInstanceToDelete = NULL; const int kNumActiveSmokeInstances = m_numActiveSmokeInstances; uint32 otherSmokeInstanceProximityCount = 0; SSmokeInstance* pOtherSmokeInstance = NULL; PrefetchLine(m_smokeInstances, 0); PrefetchLine(m_smokeInstances, 128); // Find oldest smoke grenade effect in proximity for(int i=0; i<kNumActiveSmokeInstances; i++) { pOtherSmokeInstance = &m_smokeInstances[i]; if(pOtherSmokeInstance != &smokeInstance) { PrefetchLine(pOtherSmokeInstance, 128); const float fDistanceSq = Distance::Point_PointSq(smokeInstance.vPositon, pOtherSmokeInstance->vPositon); const float fCombinedRadiusSq = sqr(smokeInstance.fMaxRadius) + sqr(pOtherSmokeInstance->fMaxRadius); if(fDistanceSq < fCombinedRadiusSq) { otherSmokeInstanceProximityCount++; if(pOldestSmokeInstanceToDelete == NULL || (pOldestSmokeInstanceToDelete->fTimer < pOtherSmokeInstance->fTimer)) { pOldestSmokeInstanceToDelete = pOtherSmokeInstance; } } } } // Delete old smoke effect in proximity if there are too many if(pOldestSmokeInstanceToDelete && (otherSmokeInstanceProximityCount >= kMaxSmokeEffectsInSameArea)) { IEntity * pGrenadeToDeleteParticleEmitterFor = gEnv->pEntitySystem->GetEntity(pOldestSmokeInstanceToDelete->grenadeId); if(pGrenadeToDeleteParticleEmitterFor) { int slotCount = pGrenadeToDeleteParticleEmitterFor->GetSlotCount(); for(int i=0; i<slotCount; i++) { IParticleEmitter* pParticleEmitter = pGrenadeToDeleteParticleEmitterFor->GetParticleEmitter(i); if(pParticleEmitter) { pParticleEmitter->Activate(false); } } } pOldestSmokeInstanceToDelete->state = eSIS_ForDeletion; } smokeInstance.state = eSIS_Active_PhysicsAsleep; } } } }
////////////////////////////////////////////////////////////////////////// // IsMountedWeaponUsableWithTarget // A piece of game-code moved from CryAction when scriptbind_AI moved to the AI system ////////////////////////////////////////////////////////////////////////// int CScriptBind_Game::IsMountedWeaponUsableWithTarget(IFunctionHandler *pH) { int paramCount = pH->GetParamCount(); if(paramCount < 2) { //gEnv->pAISystem->Warning("<CScriptBind> ", "IsMountedWeaponUsableWithTarget(): too few parameters."); GameWarning("%s: too few parameters.", __FUNCTION__); return pH->EndFunction(); } GET_ENTITY(1); if(!pEntity) { //gEnv->pAISystem->Warning("<CScriptBind> ", "IsMountedWeaponUsableWithTarget(): wrong entity id in parameter 1."); GameWarning("%s: wrong entity id in parameter 1.", __FUNCTION__); return pH->EndFunction(); } IAIObject *pAI = pEntity->GetAI(); if (!pAI) { //gEnv->pAISystem->Warning("<CScriptBind> ", "IsMountedWeaponUsableWithTarget(): Entity '%s' does not have AI.", pEntity->GetName()); GameWarning("%s: Entity '%s' does not have AI.", __FUNCTION__, pEntity->GetName()); return pH->EndFunction(); } EntityId itemEntityId; ScriptHandle hdl2; if(!pH->GetParam(2, hdl2)) { //gEnv->pAISystem->Warning("<CScriptBind> ", "IsMountedWeaponUsableWithTarget(): wrong parameter 2 format."); GameWarning("%s: wrong parameter 2 format.", __FUNCTION__); return pH->EndFunction(); } itemEntityId = (EntityId) hdl2.n; if (!itemEntityId) { //gEnv->pAISystem->Warning("<CScriptBind> ", "IsMountedWeaponUsableWithTarget(): wrong entity id in parameter 2."); GameWarning("%s: wrong entity id in parameter 2.", __FUNCTION__); return pH->EndFunction(); } IGameFramework *pGameFramework = gEnv->pGame->GetIGameFramework(); IItem *pItem = pGameFramework->GetIItemSystem()->GetItem(itemEntityId); if (!pItem) { //gEnv->pAISystem->Warning("<CScriptBind> ", "entity in parameter 2 is not an item/weapon"); GameWarning("%s: entity in parameter 2 is not an item/weapon.", __FUNCTION__); return pH->EndFunction(); } float minDist = 7; bool bSkipTargetCheck = false; Vec3 targetPos(ZERO); if(paramCount > 2) { for(int i = 3; i <= paramCount ; i++) { if(pH->GetParamType(i) == svtBool) { pH->GetParam(i, bSkipTargetCheck); } else if(pH->GetParamType(i) == svtNumber) { pH->GetParam(i, minDist); } else if(pH->GetParamType(i) == svtObject) { pH->GetParam(i, targetPos); } } } IAIActor *pAIActor = CastToIAIActorSafe(pAI); if (!pAIActor) { GameWarning("%s: entity '%s' in parameter 1 is not an AI actor.", __FUNCTION__, pEntity->GetName()); return pH->EndFunction(); } IEntity *pItemEntity = pItem->GetEntity(); if(!pItemEntity) { return pH->EndFunction(); } if(!pItem->GetOwnerId()) { // weapon is not used, check if it is on a vehicle IEntity *pParentEntity = pItemEntity->GetParent(); if(pParentEntity) { IAIObject *pParentAI = pParentEntity->GetAI(); if(pParentAI && pParentAI->GetAIType() == AIOBJECT_VEHICLE) { // (MATT) Feature was cut and code was tricky, hence ignore weapons in vehicles {2008/02/15:11:08:51} return pH->EndFunction(); } } } else if( pItem->GetOwnerId() != pEntity->GetId()) // item is used by someone else? { return pH->EndFunction(false); } // check target if(bSkipTargetCheck) { return pH->EndFunction(true); } IAIObject *pTarget = pAIActor->GetAttentionTarget(); if(targetPos.IsZero()) { if(!pTarget) { return pH->EndFunction(); } targetPos = pTarget->GetPos(); } Vec3 targetDir(targetPos - pItemEntity->GetWorldPos()); Vec3 targetDirXY(targetDir.x, targetDir.y, 0); float length2D = targetDirXY.GetLength(); if(length2D < minDist || length2D <= 0) { return pH->EndFunction(); } targetDirXY /= length2D;//normalize Vec3 mountedAngleLimits(pItem->GetMountedAngleLimits()); float yawRange = DEG2RAD(mountedAngleLimits.z); if(yawRange > 0 && yawRange < gf_PI) { float deltaYaw = pItem->GetMountedDir().Dot(targetDirXY); if(deltaYaw < cosf(yawRange)) { return pH->EndFunction(false); } } float minPitch = DEG2RAD(mountedAngleLimits.x); float maxPitch = DEG2RAD(mountedAngleLimits.y); //maxPitch = (maxPitch - minPitch)/2; //minPitch = -maxPitch; float pitch = atanf(targetDir.z / length2D); if ( pitch < minPitch || pitch > maxPitch ) { return pH->EndFunction(false); } if(pTarget) { IEntity *pTargetEntity = pTarget->GetEntity(); if(pTargetEntity) { // check target distance and where he's going IPhysicalEntity *phys = pTargetEntity->GetPhysics(); if(phys) { pe_status_dynamics dyn; phys->GetStatus(&dyn); Vec3 velocity ( dyn.v); velocity.z = 0; float speed = velocity.GetLength2D(); if(speed > 0) { //velocity /= speed; if(length2D < minDist * 0.75f && velocity.Dot(targetDirXY) <= 0) { return pH->EndFunction(false); } } } } } return pH->EndFunction(true); }
void CTornado::UpdateFlow() { IVehicleSystem* pVehicleSystem = g_pGame->GetIGameFramework()->GetIVehicleSystem(); assert(pVehicleSystem); float frameTime(gEnv->pTimer->GetFrameTime()); IPhysicalWorld *ppWorld = gEnv->pPhysicalWorld; Vec3 pos(GetEntity()->GetWorldPos()); //first, check the entities in range m_nextEntitiesCheck -= frameTime; if (m_nextEntitiesCheck<0.0f) { m_nextEntitiesCheck = 1.0f; Vec3 radiusVec(m_radius,m_radius,0); IPhysicalEntity **ppList = NULL; int numEnts = ppWorld->GetEntitiesInBox(pos-radiusVec,pos+radiusVec+Vec3(0,0,m_cloudHeight*0.5f),ppList,ent_sleeping_rigid|ent_rigid|ent_living); m_spinningEnts.clear(); for (int i=0;i<numEnts;++i) { // add check for spectating players... EntityId id = ppWorld->GetPhysicalEntityId(ppList[i]); CActor* pActor = static_cast<CActor*>(g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(id)); if(!pActor || !pActor->GetSpectatorMode()) { m_spinningEnts.push_back(id); } } //OutputDistance(); } //mess entities around for (size_t i=0;i<m_spinningEnts.size();++i) { IPhysicalEntity *ppEnt = ppWorld->GetPhysicalEntityById(m_spinningEnts[i]); if (ppEnt) { pe_status_pos spos; pe_status_dynamics sdyn; if (!ppEnt->GetStatus(&spos) || !ppEnt->GetStatus(&sdyn)) continue; //gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(spos.pos,2.0f,ColorB(255,0,255,255)); Vec3 delta(pos - spos.pos); delta.z = 0.0f; float dLen(delta.len()); float forceMult(max(0.0f,(m_radius-dLen)/m_radius)); if (dLen>0.001f) delta /= dLen; else delta.zero(); Vec3 upVector(0,0,1); float spinImpulse(m_spinImpulse); float attractionImpulse(m_attractionImpulse); float upImpulse(m_upImpulse); if (ppEnt->GetType() == PE_LIVING) { upImpulse *= 0.75f; attractionImpulse *= 0.35f; spinImpulse *= 1.5f; } if (IVehicle* pVehicle = pVehicleSystem->GetVehicle(m_spinningEnts[i])) { IVehicleMovement* pMovement = pVehicle->GetMovement(); if (pMovement && pMovement->GetMovementType() == IVehicleMovement::eVMT_Air) { SVehicleMovementEventParams params; params.fValue = forceMult; pMovement->OnEvent(IVehicleMovement::eVME_Turbulence, params); } } Vec3 spinForce( (delta % upVector) * spinImpulse ); Vec3 attractionForce(delta * attractionImpulse); Vec3 upForce(0,0,upImpulse); pe_action_impulse aimpulse; aimpulse.impulse = (spinForce + attractionForce + upForce) * (forceMult * sdyn.mass * frameTime); aimpulse.angImpulse = (upVector + (delta % upVector)) * (gf_PI * 0.33f * forceMult * sdyn.mass * frameTime); aimpulse.iApplyTime = 0; ppEnt->Action(&aimpulse); //gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(spos.pos,ColorB(255,0,255,255),spos.pos+aimpulse.impulse.GetNormalizedSafe(ZERO),ColorB(255,0,255,255)); } } }
void CAVMine::ProcessEvent(SEntityEvent &event) { if (m_frozen) return; switch(event.event) { case ENTITY_EVENT_ENTERAREA: { IEntity * pEntity = gEnv->pEntitySystem->GetEntity(event.nParam[0]); CGameRules* pGR = g_pGame->GetGameRules(); if(pEntity && pGR) { // if this is a team game, mines aren't set off by their own team if(pGR->GetTeamCount() > 0 && (m_teamId != 0 && pGR->GetTeam(pEntity->GetId()) == m_teamId)) break; // otherwise, not set off by the player who dropped them. if(pGR->GetTeamCount() == 0 && m_ownerId == pEntity->GetId()) break; // or a vehicle that player might happen to be in IVehicle* pVehicle = g_pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(event.nParam[0]); if(pVehicle && pVehicle->GetSeatForPassenger(m_ownerId)) break; IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus)) { // only count moving objects if(physStatus.v.GetLengthSquared() > 0.1f) m_currentWeight += physStatus.mass; if (m_currentWeight > m_triggerWeight) Explode(true); } } } break; } case ENTITY_EVENT_LEAVEAREA: { IEntity * pEntity = gEnv->pEntitySystem->GetEntity(event.nParam[0]); if(pEntity) { IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus)) { m_currentWeight -= physStatus.mass; if(m_currentWeight < 0) m_currentWeight = 0; } } } break; } default: break; } return CProjectile::ProcessEvent(event); }
//------------------------------------------------------------------------ float CGameRulesCommonDamageHandling::GetCollisionEnergy( const IEntity *pVictim, const CGameRules::SCollisionHitInfo& colHitInfo ) const { float m1 = colHitInfo.target_mass; float m0 = 0.f; IPhysicalEntity *phys = pVictim->GetPhysics(); if(phys) { pe_status_dynamics dyn; phys->GetStatus(&dyn); m0 = dyn.mass; } IEntity *pOffender = gEnv->pEntitySystem->GetEntity(colHitInfo.targetId); bool bCollider = (pOffender || m1 > 0.001f); const bool debugColl = DebugCollisions(); if (debugColl) { CryLog("GetCollisionEnergy %s (%.1f) <-> %s (%.1f)", pVictim?pVictim->GetName():"[no entity]", m0, pOffender?pOffender->GetName():"[no entity]", m1); } float v0Sq = 0.f, v1Sq = 0.f; if (bCollider) // non-static { m0 = min(m0, m1); Vec3 v0normal, v1normal, vrel; Vec3 tempNormal = colHitInfo.normal; float v0dotN = colHitInfo.velocity.dot(colHitInfo.normal); v0normal = tempNormal.scale(v0dotN); float v1dotN = colHitInfo.target_velocity.dot(colHitInfo.normal);; // "target" is the offender v1normal = tempNormal.scale(v1dotN); vrel = v0normal.sub(v1normal); float vrelSq = vrel.len2(); v0Sq = min( sqr(v0dotN), vrelSq ); v1Sq = min( sqr(v1dotN), vrelSq ); if (debugColl) { IPersistantDebug* pPD = g_pGame->GetIGameFramework()->GetIPersistantDebug(); pPD->Begin("CollDamage", false); pPD->AddSphere(colHitInfo.pos, 0.15f, Col_Red, 5.f); pPD->AddDirection(colHitInfo.pos, 1.5f, tempNormal.scale(sgn(v0dotN)), Col_Green, 5.f); pPD->AddDirection(colHitInfo.pos, 1.5f, tempNormal.scale(sgn(v1dotN)), Col_Red, 5.f); if ((v0Sq > 2*2) || (v1Sq > 2*2)) { CryLog("normal velocities: rel %.1f, <%s> %.1f / <%s> %.1f", sqrt(vrelSq), pVictim?pVictim->GetName():"none", v0dotN, pOffender?pOffender->GetName():"none", v1dotN); CryLog("target_type: %i, target_velocity: %.2f %.2f %.2f", colHitInfo.target_type, colHitInfo.target_velocity.x, colHitInfo.target_velocity.y, colHitInfo.target_velocity.z); } } } else { v0Sq = sqr(colHitInfo.velocity.dot(colHitInfo.normal)); if (debugColl && v0Sq>5*5) { IPersistantDebug* pPD = g_pGame->GetIGameFramework()->GetIPersistantDebug(); pPD->Begin("CollDamage", false); pPD->AddDirection(colHitInfo.pos, 1.5f, colHitInfo.normal, Col_Green, 5.f); string debugText; debugText.Format("z: %f", colHitInfo.velocity.z); pPD->Add2DText(debugText.c_str(), 1.5f, Col_White, 5.f); } } float colliderEnergyScale = 1.f; if (pVictim != NULL && pOffender != NULL) { if(IActor* pVictimActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pVictim->GetId())) { colliderEnergyScale = !pVictimActor->IsPlayer() ? GetAIPlayerAgainstColliderEnergyScale(*pOffender) : GetPlayerAgainstColliderEnergyScale(*pOffender); if (debugColl) { CryLog("colliderEnergyScale: %.1f", colliderEnergyScale); } } } const float energy0 = 0.5f * m0 * v0Sq; const float energy1 = 0.5f * m1 * v1Sq * colliderEnergyScale; return energy0 + energy1; }
//------------------------------------------------------------------------ bool CGameRules::OnInitiate(SHostMigrationInfo& hostMigrationInfo, uint32& state) { if (!g_pGame->GetIGameFramework()->ShouldMigrateNub(hostMigrationInfo.m_session)) { return true; } CryLog("[Host Migration]: CGameRules::OnInitiate() Saving character for host migration started"); m_hostMigrationClientHasRejoined = false; IEntityScriptProxy* pScriptProxy = static_cast<IEntityScriptProxy*>(GetEntity()->GetProxy(ENTITY_PROXY_SCRIPT)); if (pScriptProxy) { if (string(pScriptProxy->GetState()) == "InGame") { m_hostMigrationTimeSinceGameStarted = (m_cachedServerTime - m_gameStartedTime); } } HostMigrationStopAddingPlayers(); if (gEnv->IsClient()) { if (!m_pHostMigrationParams) { m_pHostMigrationParams = new SHostMigrationClientRequestParams(); m_pHostMigrationClientParams = new SHostMigrationClientControlledParams(); } IActor *pPlayer = g_pGame->GetIGameFramework()->GetClientActor(); if (pPlayer) { m_pHostMigrationClientParams->m_viewQuat = pPlayer->GetViewRotation(); m_pHostMigrationClientParams->m_position = pPlayer->GetEntity()->GetPos(); pe_status_living livStat; IPhysicalEntity *pPhysicalEntity = pPlayer->GetEntity()->GetPhysics(); if (pPhysicalEntity != NULL && (pPhysicalEntity->GetType() == PE_LIVING) && (pPhysicalEntity->GetStatus(&livStat) > 0)) { m_pHostMigrationClientParams->m_velocity = livStat.velUnconstrained; m_pHostMigrationClientParams->m_hasValidVelocity = true; CryLog(" velocity={%f,%f,%f}", m_pHostMigrationClientParams->m_velocity.x, m_pHostMigrationClientParams->m_velocity.y, m_pHostMigrationClientParams->m_velocity.z); } IInventory *pInventory = pPlayer->GetInventory(); m_pHostMigrationClientParams->m_numExpectedItems = 0; int numAmmoTypes = 0; m_pHostMigrationClientParams->m_pAmmoParams = new SHostMigrationClientControlledParams::SAmmoParams[numAmmoTypes]; m_pHostMigrationClientParams->m_numAmmoParams = numAmmoTypes; /*CryLog(" player has %i different ammo types", numAmmoTypes); for (int i = 0; i < numAmmoTypes; ++ i) { IEntityClass *pAmmoType = pInventory->GetAmmoType(i); int ammoCount = pInventory->GetAmmoCount(pAmmoType); m_pHostMigrationClientParams->m_pAmmoParams[i].m_pAmmoClass = pAmmoType; m_pHostMigrationClientParams->m_pAmmoParams[i].m_count = ammoCount; CryLog(" %s : %i", pAmmoType->GetName(), ammoCount); }* EntityId holseredItemId = pInventory->GetHolsteredItem(); if (holseredItemId) { IEntity *pHolsteredEntity = gEnv->pEntitySystem->GetEntity(holseredItemId); if (pHolsteredEntity) { m_pHostMigrationClientParams->m_pHolsteredItemClass = pHolsteredEntity->GetClass(); } }*/ IMovementController *pMovementController = pPlayer->GetMovementController(); if(pMovementController) { SMovementState movementState; pMovementController->GetMovementState(movementState); m_pHostMigrationClientParams->m_aimDirection = movementState.aimDirection; } /*CItem *pItem = static_cast<CItem*>(pPlayer->GetCurrentItem()); if (pItem) { m_pHostMigrationClientParams->m_pSelectedItemClass = pItem->GetEntity()->GetClass(); CryLog(" currently using item '%s", pItem->GetEntity()->GetName()); }*/ } else { CRY_ASSERT_MESSAGE(false, "Failed to find client actor when initiating a host migration"); gEnv->pNetwork->TerminateHostMigration(hostMigrationInfo.m_session); return false; } } g_pGame->SetHostMigrationState(CGame::eHMS_WaitingForPlayers); CCCPOINT(HostMigration_OnInitiate); return true; }
////////////////////////////////////////////////////////////////////////// // NOTE: This function must be thread-safe. Before adding stuff contact MarcoC. void CVehicleMovementHelicopter::ProcessMovement(const float deltaTime) { FUNCTION_PROFILER( GetISystem(), PROFILE_GAME ); IPhysicalEntity* pPhysics = GetPhysics(); assert(pPhysics); if (m_arcade.m_handling.maxSpeedForward>0.f) // Use the new handling code { CryAutoCriticalSection lk(m_lock); if (!m_isEnginePowered) return; CVehicleMovementBase::ProcessMovement(deltaTime); SVehiclePhysicsStatus* physStatus = &m_physStatus[k_physicsThread]; if(m_bApplyNoiseAsVelocity) { physStatus->v -= m_pNoise->m_posDifference; physStatus->w -= m_pNoise->m_angDifference; m_pNoise->Update(deltaTime); } /////////////////////////////////////////////////////////////// // Pass on the movement request to the active physics handler // NB: m_physStatus is update by this call SVehiclePhysicsHelicopterProcessParams params; params.pPhysics = pPhysics; params.pPhysStatus = physStatus; params.pInputAction = &m_inputAction; params.dt = deltaTime; params.haveDriver = (m_actorId!=0)||m_remotePilot; params.isAI = m_movementAction.isAI; params.aiRequiredVel = m_CurrentVel; m_arcade.ProcessMovement(params); // Network error adjustment m_netPosAdjust *= max(0.f, 1.f-deltaTime*k_netErrorPosScale); physStatus->v += m_netPosAdjust * k_netErrorPosScale; if(m_bApplyNoiseAsVelocity) { physStatus->v += m_pNoise->m_posDifference; physStatus->w += m_pNoise->m_angDifference; } //=============================================== // Commit the velocity back to the physics engine //=============================================== // if (fabsf(m_movementAction.rotateYaw)>0.05f || vel.GetLengthSquared()>0.001f || m_chassis.vel.GetLengthSquared()>0.001f || angVel.GetLengthSquared()>0.001f || angVel.GetLengthSquared()>0.001f) { pe_action_set_velocity setVelocity; setVelocity.v = physStatus->v; setVelocity.w = physStatus->w; pPhysics->Action(&setVelocity, 1); } /////////////////////////////////////////////////////////////// } else { if (m_isEnginePowered && pPhysics) { m_movementAction.isAI = true; pe_status_pos psp; pe_status_dynamics psd; if (!pPhysics->GetStatus(&psp) || !pPhysics->GetStatus(&psd)) return; UpdatePhysicsStatus(&m_physStatus[k_physicsThread], &psp, &psd); ProcessAI(deltaTime); } } }
//------------------------------------------------------------------------ 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]; _snprintf(buf, sizeof(buf), "%s_%02i", name.c_str(), p); buf[sizeof(buf)-1] = '\0'; 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!",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 CAVMine::ProcessEvent(SEntityEvent &event) { if (m_frozen) return; switch(event.event) { case ENTITY_EVENT_ENTERAREA: { IEntity * pEntity = gEnv->pEntitySystem->GetEntity((EntityId)event.nParam[0]); CGameRules* pGR = g_pGame->GetGameRules(); if(pEntity && pGR) { // if this is a team game, mines aren't set off by their own team if(pGR->GetTeamCount() > 0 && (m_teamId != 0 && pGR->GetTeam(pEntity->GetId()) == m_teamId)) break; IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus)) { // only count moving objects if(physStatus.v.GetLengthSquared() > 0.1f) m_currentWeight += physStatus.mass; if (m_currentWeight > m_triggerWeight) Explode(true); } } } break; } case ENTITY_EVENT_LEAVEAREA: { IEntity * pEntity = gEnv->pEntitySystem->GetEntity((EntityId)event.nParam[0]); if(pEntity) { IPhysicalEntity *pPhysics = pEntity->GetPhysics(); if(pPhysics) { pe_status_dynamics physStatus; if(0 != pPhysics->GetStatus(&physStatus)) { m_currentWeight -= physStatus.mass; if(m_currentWeight < 0) m_currentWeight = 0; } } } break; } default: break; } return CProjectile::ProcessEvent(event); }
//------------------------------------------------------------------------ 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(); }
//------------------------------------------------------------------------ Vec3 CGunTurret::PredictTargetPos(IEntity *pTarget, bool sec)//sec - weapon to use { pTarget = ResolveTarget(pTarget); Vec3 tpos = GetTargetPos(pTarget); if(m_turretparams.search_only || m_turretparams.prediction == 0.f) return tpos; IPhysicalEntity *pe = pTarget->GetPhysics(); pe_status_dynamics dyn; if(!pe || !pe->GetStatus(&dyn)) return tpos; Vec3 vel = dyn.v; Vec3 acc = dyn.a; float a = acc.len(); if(a < 0.01f) a = 0.f; else acc /= a; Vec3 vpos = GetWeaponPos(); Vec3 dist = tpos-vpos; float d = dist.len(); if(d < 0.01f) return tpos; dist /= d; float d_speed = vel*dist; float speed = 800.0f; const SAmmoParams *ammo = g_pGame->GetWeaponSystem()->GetAmmoParams(GetFireMode(0)->GetAmmoType()); if(!ammo) return tpos; if(ammo->physicalizationType == ePT_None) return tpos; speed = ammo->speed; float time_to = d/max(1.f, speed-d_speed); // MR: clamped acc prediction to reduce jerkyness when targetting objects that are able // to do near-instant velocity changes (like players) a = min(a, 25.f); Vec3 delta = vel*(time_to) + 0.5f*a*acc*time_to*time_to; delta *= m_turretparams.prediction; if(g_pGameCVars->i_debug_turrets == eGTD_Prediction) { IPersistantDebug *pDebug = gEnv->pGame->GetIGameFramework()->GetIPersistantDebug(); pDebug->Begin("CGunTurret::PredictTargetPos", false); pDebug->AddSphere(tpos+delta, 0.2f, ColorF(1,0,0,1), 1.f); gEnv->pRenderer->DrawLabel(vpos, 1.4f, "Predict %s: speed %.1f (dspeed %.1f), acc %.1f, time %.1f", pTarget->GetName(), vel.len(), d_speed, a, time_to); } return tpos+delta; }
//------------------------------------------------------------------------ bool CGameRules::OnInitiate(SHostMigrationInfo &hostMigrationInfo, uint32 &state) { if (!g_pGame->GetIGameFramework()->ShouldMigrateNub(hostMigrationInfo.m_session)) { return true; } CryLog("[Host Migration]: CGameRules::OnInitiate() Saving character for host migration started"); m_hostMigrationClientHasRejoined = false; IEntityScriptProxy *pScriptProxy = static_cast<IEntityScriptProxy *>(GetEntity()->GetProxy(ENTITY_PROXY_SCRIPT)); if (pScriptProxy) { if (string(pScriptProxy->GetState()) == "InGame") { m_hostMigrationTimeSinceGameStarted = (m_cachedServerTime - m_gameStartedTime); } } HostMigrationStopAddingPlayers(); if (gEnv->IsClient()) { if (!m_pHostMigrationParams) { m_pHostMigrationParams = new SHostMigrationClientRequestParams(); m_pHostMigrationClientParams = new SHostMigrationClientControlledParams(); } CPlayer *pPlayer = static_cast<CPlayer *>(g_pGame->GetIGameFramework()->GetClientActor()); if (pPlayer) { m_pHostMigrationClientParams->m_viewQuat = pPlayer->GetViewRotation(); m_pHostMigrationClientParams->m_position = pPlayer->GetEntity()->GetPos(); pe_status_living livStat; IPhysicalEntity *pPhysicalEntity = pPlayer->GetEntity()->GetPhysics(); if (pPhysicalEntity != NULL && (pPhysicalEntity->GetType() == PE_LIVING) && (pPhysicalEntity->GetStatus(&livStat) > 0)) { m_pHostMigrationClientParams->m_velocity = livStat.velUnconstrained; m_pHostMigrationClientParams->m_hasValidVelocity = true; CryLog(" velocity={%f,%f,%f}", m_pHostMigrationClientParams->m_velocity.x, m_pHostMigrationClientParams->m_velocity.y, m_pHostMigrationClientParams->m_velocity.z); } IMovementController *pMovementController = pPlayer->GetMovementController(); SMovementState movementState; pMovementController->GetMovementState(movementState); m_pHostMigrationClientParams->m_aimDirection = movementState.aimDirection; } else { CRY_ASSERT_MESSAGE(false, "Failed to find client actor when initiating a host migration"); gEnv->pNetwork->TerminateHostMigration(hostMigrationInfo.m_session); return false; } } g_pGame->SetHostMigrationState(CGame::eHMS_WaitingForPlayers); CCCPOINT(HostMigration_OnInitiate); return true; }