//------------------------------------------------------------------------ void CCannonBall::ProcessHit(CGameRules& gameRules, const EventPhysCollision& collision, IEntity& target, float damage, int hitMatId, const Vec3& hitDir) { if(damage > 0.f) { EntityId targetId = target.GetId(); bool alreadyHit = CheckForPreviousHit(targetId, damage); if(!alreadyHit) { HitInfo hitInfo(m_ownerId ? m_ownerId : m_hostId, targetId, m_weaponId, damage, 0.0f, hitMatId, collision.partid[1], m_hitTypeId, collision.pt, hitDir, collision.n); hitInfo.remote = IsRemote(); hitInfo.projectileId = GetEntityId(); hitInfo.bulletType = m_pAmmoParams->bulletType; hitInfo.knocksDown = CheckAnyProjectileFlags(ePFlag_knocksTarget) && ( damage > m_minDamageForKnockDown ); hitInfo.knocksDownLeg = m_chanceToKnockDownLeg>0 && damage>m_minDamageForKnockDownLeg && m_chanceToKnockDownLeg>(int)Random(100); hitInfo.penetrationCount = m_penetrationCount; hitInfo.hitViaProxy = CheckAnyProjectileFlags(ePFlag_firedViaProxy); hitInfo.aimed = CheckAnyProjectileFlags(ePFlag_aimedShot); IPhysicalEntity* pPhysicalEntity = collision.pEntity[1]; if (pPhysicalEntity && pPhysicalEntity->GetType() == PE_ROPE) { hitInfo.partId = GetRopeBoneId(collision, target, pPhysicalEntity); } gameRules.ClientHit(hitInfo); ReportHit(targetId); } } }
bool CMFXParticleEffect::AttachToTarget( const SMFXParticleEntry& particleParams, const SMFXRunTimeEffectParams& params, IParticleEffect* pParticleEffect, const Vec3& dir, float scale ) { bool shouldTryToAttach = particleParams.attachToTarget && (params.trg != 0); if (!shouldTryToAttach) { return false; } IEntity* pTargetEntity = gEnv->pEntitySystem->GetEntity(params.trg); if (pTargetEntity) { //Try to figure out if it's a character using physics type IPhysicalEntity* pTargetPhysics = pTargetEntity->GetPhysics(); int physicsType = pTargetPhysics ? pTargetPhysics->GetType() : PE_NONE; bool isCharacter = (physicsType == PE_LIVING) || (physicsType == PE_ARTICULATED); if (isCharacter) { return AttachToCharacter(*pTargetEntity, particleParams, params, dir, scale); } //else //{ //return AttachToEntity(*pTargetEntity, particleParams, params, pParticleEffect, dir, scale); //} } return false; }
EntityId CAICorpseManager::SpawnAICorpseFromEntity( IEntity& sourceEntity, const SCorpseParameters& corpseParams ) { assert(gEnv->IsEditor() == false); assert(gEnv->bMultiplayer == false); if(g_pGameCVars->g_aiCorpses_Enable == 0) return 0; if(m_corpsesArray.size() == m_maxCorpses) { RemoveSomeCorpses(); assert((uint32)m_corpsesArray.size() < m_maxCorpses); } MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, EMemStatContextFlags::MSF_None, "AICorpseManager::SpawnCorpse"); EntityId corpseId = 0; IPhysicalEntity* pSourcePhysics = sourceEntity.GetPhysics(); if ((pSourcePhysics != NULL) && (pSourcePhysics->GetType() == PE_ARTICULATED)) { ICharacterInstance *pSourceCharacterInstance = sourceEntity.GetCharacter(0); if (pSourceCharacterInstance != NULL) { IEntityClass *pCorpseClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("AICorpse"); assert(pCorpseClass); stack_string corpseName; corpseName.Format("%s_Corpse", sourceEntity.GetName()); SEntitySpawnParams params; params.pClass = pCorpseClass; params.sName = corpseName.c_str(); #if !AI_CORPSES_ENABLE_SERIALIZE params.nFlags |= ENTITY_FLAG_NO_SAVE; #endif params.vPosition = sourceEntity.GetWorldPos(); params.qRotation = sourceEntity.GetWorldRotation(); IEntity *pCorpseEntity = gEnv->pEntitySystem->SpawnEntity(params, true); if(pCorpseEntity != NULL) { corpseId = pCorpseEntity->GetId(); CorpseInfo* pCorpseInfo = FindCorpseInfo( corpseId ); assert(pCorpseInfo != NULL); CAICorpse* pCorpse = pCorpseInfo->GetCorpse(); assert(pCorpse != NULL); pCorpse->SetupFromSource( sourceEntity, *pSourceCharacterInstance, (uint32)corpseParams.priority); } } } return corpseId; }
void CReplayActor::OnRagdollized() { if(!m_ragdollImpulse.impulse.IsZero()) { IPhysicalEntity* pPhys = GetEntity()->GetPhysics(); CRY_ASSERT(pPhys && pPhys->GetType()==PE_ARTICULATED); pPhys->Action(&m_ragdollImpulse); } m_ragdollImpulse.impulse.zero(); }
void CReplayActor::ApplyRagdollImpulse( pe_action_impulse& impulse ) { IPhysicalEntity* pPhys = GetEntity()->GetPhysics(); if(!pPhys || pPhys->GetType()!=PE_ARTICULATED) { m_ragdollImpulse = impulse; } else { pPhys->Action(&impulse); } }
void ResetVelocity(SActivationInfo* pActInfo) { IEntity* pGraphEntity = pActInfo->pEntity; if (pGraphEntity) { IPhysicalEntity* pPhysicalEntity = pGraphEntity->GetPhysics(); if (pPhysicalEntity && pPhysicalEntity->GetType() != PE_STATIC) { pe_action_set_velocity setVel; setVel.v.zero(); setVel.w.zero(); pPhysicalEntity->Action(&setVel); } } }
//------------------------------------------------------------------------ void CThrow::Update(float frameTime, uint32 frameId) { CSingle::Update(frameTime, frameId); if (m_firing) { if (!m_pulling && !m_throwing && !m_thrown) { if(m_hold_timer > 0.0f) { m_hold_timer -= frameTime; if (m_hold_timer < 0.0f) { m_hold_timer = 0.0f; } } } else if (m_throwing && m_throw_time <= 0.0f) { CActor *pOwner = m_pWeapon->GetOwnerActor(); m_pWeapon->HideItem(true); if (m_throwableId) { IEntity *pEntity = gEnv->pEntitySystem->GetEntity(m_throwableId); if (pEntity) { if (m_throwableAction) { m_throwableAction->execute(m_pWeapon); } IPhysicalEntity *pPE = pEntity->GetPhysics(); if (pPE && (pPE->GetType() == PE_RIGID || pPE->GetType() == PE_PARTICLE)) { ThrowObject(pEntity, pPE); } else if (pPE && (pPE->GetType() == PE_LIVING || pPE->GetType() == PE_ARTICULATED)) { ThrowLivingEntity(pEntity, pPE); } } } else if (!m_netfiring) { ThrowGrenade(); } m_throwing = false; } else if (m_thrown && m_throw_time <= 0.0f) { m_pWeapon->SetBusy(false); m_pWeapon->HideItem(false); int ammoCount = m_pWeapon->GetAmmoCount(m_pShared->fireparams.ammo_type_class); if (ammoCount > 0) { m_pWeapon->PlayAction(m_pShared->throwactions.next); } else if (m_pShared->throwparams.auto_select_last) { static_cast<CPlayer *>(m_pWeapon->GetOwnerActor())->SelectLastItem(true); } m_firing = false; m_throwing = false; m_thrown = false; } m_throw_time -= frameTime; if (m_throw_time < 0.0f) { m_throw_time = 0.0f; } m_pWeapon->RequireUpdate(eIUS_FireMode); } }
//-------------------------------------- void CThrow::DoDrop() { m_pWeapon->HideItem(true); if (m_throwableId) { IEntity *pEntity = gEnv->pEntitySystem->GetEntity(m_throwableId); if (pEntity) { IPhysicalEntity *pPE = pEntity->GetPhysics(); if (pPE && (pPE->GetType() == PE_RIGID || pPE->GetType() == PE_PARTICLE)) { Vec3 hit = GetProbableHit(WEAPON_HIT_RANGE); Vec3 pos = GetFiringPos(hit); CActor *pActor = m_pWeapon->GetOwnerActor(); IMovementController *pMC = pActor ? pActor->GetMovementController() : 0; if (pMC) { SMovementState info; pMC->GetMovementState(info); float speed = 2.5f; CPlayer *pPlayer = static_cast<CPlayer *>(m_pWeapon->GetOwnerActor()); if(info.aimDirection.z < -0.1f) { if(pPlayer) { if(SPlayerStats *pStats = static_cast<SPlayerStats *>(pPlayer->GetActorStats())) { if(pStats->grabbedHeavyEntity) { speed = 4.0f; } } } } if(CheckForIntersections(pPE, info.eyeDirection)) { Matrix34 newTM = pEntity->GetWorldTM(); newTM.SetTranslation(newTM.GetTranslation() - (info.eyeDirection * 0.4f)); pEntity->SetWorldTM(newTM, ENTITY_XFORM_POS); pe_action_set_velocity asv; asv.v = (-info.eyeDirection * speed); pPE->Action(&asv); } else { pe_action_set_velocity asv; asv.v = (info.eyeDirection * speed); pPE->Action(&asv); } SEntityEvent entityEvent; entityEvent.event = ENTITY_EVENT_PICKUP; entityEvent.nParam[0] = 0; if (pPlayer) { entityEvent.nParam[1] = pPlayer->GetEntityId(); } entityEvent.fParam[0] = speed; pEntity->SendEvent( entityEvent ); } } } if (m_throwableAction) { m_throwableAction->execute(m_pWeapon); } } }
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)); } } }
//-------------------------------------------------------------------------------------------------- // Name: HandleImpact // Desc: Passes an impact on to the simulation //-------------------------------------------------------------------------------------------------- int CBreakableGlassSystem::HandleImpact(const EventPhys* pPhysEvent) { if (CCryAction* pCryAction = CCryAction::GetCryAction()) { if (CBreakableGlassSystem* pGlassSystem = static_cast<CBreakableGlassSystem*>(pCryAction->GetIBreakableGlassSystem())) { pGlassSystem->AssertUnusedIfDisabled(); if (pGlassSystem->m_enabled) { if (const EventPhysCollision* pCollEvent = static_cast<const EventPhysCollision*>(pPhysEvent)) { // Glass fragments always get destroyed on their first collision const uint physFrag = (pCollEvent->iForeignData[0] == PHYS_FOREIGN_ID_BREAKABLE_GLASS_FRAGMENT) ? 0 : 1; IPhysicalEntity* pPhysEnt = pCollEvent->pEntity[physFrag]; if (pPhysEnt && pCollEvent->iForeignData[physFrag] == PHYS_FOREIGN_ID_BREAKABLE_GLASS_FRAGMENT) { // Fragments only collide with non-glass geometry const int nonFragType = pCollEvent->iForeignData[1-physFrag]; if (nonFragType != PHYS_FOREIGN_ID_BREAKABLE_GLASS && nonFragType != PHYS_FOREIGN_ID_BREAKABLE_GLASS_FRAGMENT && nonFragType != PHYS_FOREIGN_ID_ENTITY) // Only break on floors, walls, etc. { // Verify parent glass node, then allow it to handle impact if (SGlassPhysFragment* pPhysFrag = (SGlassPhysFragment*)pCollEvent->pForeignData[physFrag]) { if (IBreakableGlassRenderNode* pRenderNode = (IBreakableGlassRenderNode*)pPhysFrag->m_pRenderNode) { pRenderNode->DestroyPhysFragment(pPhysFrag); } } } } else if (pCollEvent->iForeignData[PHYSEVENT_COLLIDEE] == PHYS_FOREIGN_ID_BREAKABLE_GLASS) { // Get breakable glass data PodArray<IBreakableGlassRenderNode*>& glassPlanes = pGlassSystem->m_glassPlanes; const int numPlanes = glassPlanes.Count(); // Duplicate event so we can freely manipulate it EventPhysCollision dupeEvent = *pCollEvent; const EventPhysCollision* pDupeEvent = (const EventPhysCollision*)&dupeEvent; // Some actors can force breaks for gameplay reasons IPhysicalEntity* pCollider = dupeEvent.pEntity[PHYSEVENT_COLLIDER]; if (pCollider && pCollider->GetType() == PE_LIVING) { IEntity* pColliderEntity = (IEntity*)pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY); IActor* pActor = pColliderEntity ? gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pColliderEntity->GetId()) : NULL; if (pActor && pActor->MustBreakGlass()) { pGlassSystem->ModifyEventToForceBreak(&dupeEvent); } } // Verify glass node and pass impact through IBreakableGlassRenderNode* pRenderNode = (IBreakableGlassRenderNode*)pCollEvent->pForeignData[PHYSEVENT_COLLIDEE]; const int targetId = pRenderNode ? pRenderNode->GetId() : numPlanes; if (targetId < numPlanes && pRenderNode == glassPlanes[targetId]) { pGlassSystem->PassImpactToNode(pRenderNode, pDupeEvent); } } } } } } return 1; // Pass event to other handlers even if we processed it }//-------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------ 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; }
//----------------------------------------------- //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; } }
virtual void ProcessEvent( EFlowEvent event,SActivationInfo* pActInfo ) { switch (event) { case eFE_Activate: { m_lastTime = gEnv->pTimer->GetFrameStartTime(); m_bActive = !GetPortBool(pActInfo, 1); pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, m_bActive ); if (!m_bActive) { ResetVelocity(pActInfo); } } break; case eFE_Initialize: { if (pActInfo->pEntity) m_localRot = pActInfo->pEntity->GetRotation(); else m_localRot.SetIdentity(); m_worldRot.SetIdentity(); m_lastTime = gEnv->pTimer->GetFrameStartTime(); m_bActive = !GetPortBool(pActInfo, 1); pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, m_bActive ); break; } case eFE_Update: { if (m_bActive && pActInfo->pEntity) { CTimeValue time = gEnv->pTimer->GetFrameStartTime(); float timeDifference = (time - m_lastTime).GetSeconds(); m_lastTime = time; IEntity* pEntity = pActInfo->pEntity; const bool bUseWorld = GetPortInt(pActInfo, 2) == 0 ? true : false; Vec3 speed = GetPortVec3(pActInfo, 0); speed *= timeDifference; Quat deltaRot (Ang3(DEG2RAD(speed))); Quat finalRot; if (bUseWorld == false) { finalRot = pEntity->GetRotation(); finalRot *= deltaRot; } else { m_worldRot *= deltaRot; finalRot = m_worldRot; finalRot *= m_localRot; } finalRot.NormalizeSafe(); IPhysicalEntity* piPhysEnt = pEntity->GetPhysics(); if (piPhysEnt && piPhysEnt->GetType() != PE_STATIC) { if (timeDifference > 0.0001f) { pe_action_set_velocity asv; asv.w = Quat::log(deltaRot) * (2.f / timeDifference); asv.bRotationAroundPivot = 1; pEntity->GetPhysics()->Action(&asv); } } else { pEntity->SetRotation(finalRot); } Ang3 currentAng = Ang3(finalRot); ActivateOutput(pActInfo, 1, Vec3(currentAng)); currentAng = RAD2DEG(currentAng); ActivateOutput(pActInfo, 0, Vec3(currentAng)); } break; } } }
virtual void ProcessEvent( EFlowEvent event,SActivationInfo *pActInfo ) { switch (event) { case eFE_Activate: { // update destination only if dynamic update is enabled. otherwise destination is read on Start/Reset only if (m_bActive && IsPortActive(pActInfo, IN_DEST) && GetPortBool(pActInfo, IN_DYN_DEST) == true) { ReadDestinationPosFromInput( pActInfo ); if (m_valueType==VT_TIME) CalcSpeedFromTimeInput( pActInfo ); } if (m_bActive && IsPortActive(pActInfo, IN_VALUE)) { ReadSpeedFromInput( pActInfo ); } if (IsPortActive(pActInfo, IN_START)) { Start( pActInfo ); } if (IsPortActive(pActInfo, IN_STOP)) { pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, false ); if (m_bActive) { ActivateOutput(pActInfo, OUT_DONE, true); m_bActive = false; } ActivateOutput(pActInfo, OUT_STOP, true); } // we dont support dynamic change of those inputs assert( !IsPortActive(pActInfo, IN_COORDSYS) ); assert( !IsPortActive(pActInfo, IN_VALUETYPE) ); break; } case eFE_Initialize: { m_bActive = false; m_position = ZERO; m_coorSys = (ECoordSys)GetPortInt( pActInfo, IN_COORDSYS ); m_valueType = (EValueType)GetPortInt(pActInfo, IN_VALUETYPE); IEntity *pEnt = pActInfo->pEntity; if(pEnt) m_position = pEnt->GetWorldPos(); ActivateOutput(pActInfo, OUT_CURRENT, m_position); // i dont see a sense for this, but lets keep it for now pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, false ); break; } case eFE_Update: { IEntity *pEnt = pActInfo->pEntity; if (!pEnt) { pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, false ); break; } // Use physics velocity updates, unless the entity is parented in another entity space and not rigid. IPhysicalEntity* pPhysEnt = pEnt->GetPhysics(); if( pPhysEnt && (pEnt->GetParent()!=NULL || pPhysEnt->GetType() == PE_STATIC) ) { pPhysEnt = NULL; } if (m_stopping) { m_stopping = false; pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, false ); if( pPhysEnt == NULL ) { SetPos(pActInfo, m_destination); } m_bActive = false; break; } if (!m_bActive) break; float time = gEnv->pTimer->GetFrameStartTime().GetSeconds(); float timeDifference = time - m_lastFrameTime; m_lastFrameTime = time; // note - if there's no physics then this will be the same, but if the platform is moved through physics, then // we have to get back the actual movement - this maybe framerate dependent. m_position = pActInfo->pEntity->GetPos(); // let's compute the movement vector now Vec3 oldPosition = m_position; if(m_bForceFinishAsTooNear || m_position.IsEquivalent(m_destination, 0.01f)) { m_position = m_destination; oldPosition = m_destination; ActivateOutput(pActInfo, OUT_DONE, true); ActivateOutput(pActInfo, OUT_FINISH, true); SetPos(pActInfo, m_position); // for finishing we have to make a manual setpos even if there is physics involved, to make sure the entity will be where it should. if (pPhysEnt) { pe_action_set_velocity setVel; setVel.v = ZERO; pPhysEnt->Action( &setVel ); m_stopping = true; } else { pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, false ); m_bActive = false; } } else { Vec3 direction = m_destination - m_position; float distance = direction.GetLength(); Vec3 directionAndSpeed = direction.normalized(); // ease-area calcs float distanceForEaseOutCalc = distance + m_easeOutDistance * EASE_MARGIN_FACTOR; if (distanceForEaseOutCalc < m_easeOutDistance) // takes care of m_easeOutDistance being 0 { directionAndSpeed *= distanceForEaseOutCalc / m_easeOutDistance; } else // init code makes sure both eases dont overlap, when the movement is time defined. when it is speed defined, only ease out is applied if they overlap. { if (m_easeInDistance>0.f) { Vec3 vectorFromStart = m_position - m_startPos; float distanceFromStart = vectorFromStart.GetLength(); float distanceForEaseInCalc = distanceFromStart + m_easeInDistance * EASE_MARGIN_FACTOR; if (distanceForEaseInCalc < m_easeInDistance) { directionAndSpeed *= distanceForEaseInCalc / m_easeInDistance; } } } directionAndSpeed *= (m_topSpeed * timeDifference); if(direction.GetLength() < directionAndSpeed.GetLength()) { m_position = m_destination; m_bForceFinishAsTooNear = true; } else m_position += directionAndSpeed; } ActivateOutput(pActInfo, OUT_CURRENT, m_position); if (pPhysEnt == NULL) { SetPos(pActInfo, m_position); } else { pe_action_set_velocity setVel; float rTimeStep = timeDifference>0.000001f ? 1.f / timeDifference : 0.0f; setVel.v = (m_position - oldPosition) * rTimeStep; pPhysEnt->Action( &setVel ); } break; } }; };
//------------------------------------------------------------------------ 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; }