void CGameVolume_Water::DebugDrawVolume() { IGameVolumes::VolumeInfo volumeInfo; if (GetVolumeInfoForEntity(GetEntityId(), volumeInfo) == false) return; if (volumeInfo.verticesCount < 3) return; const Matrix34 worldTM = GetEntity()->GetWorldTM(); const Vec3 depthOffset = worldTM.GetColumn2().GetNormalized() * - m_volumeDepth; IRenderAuxGeom* pRenderAux = gEnv->pRenderer->GetIRenderAuxGeom(); for (uint32 i = 0; i < volumeInfo.verticesCount - 1; ++i) { const Vec3 point1 = worldTM.TransformPoint(volumeInfo.pVertices[i]); const Vec3 point2 = worldTM.TransformPoint(volumeInfo.pVertices[i + 1]); pRenderAux->DrawLine( point1, Col_SlateBlue, point1 + depthOffset, Col_SlateBlue, 2.0f ); pRenderAux->DrawLine( point1 + depthOffset, Col_SlateBlue, point2 + depthOffset, Col_SlateBlue, 2.0f ); } const Vec3 firstPoint = worldTM.TransformPoint(volumeInfo.pVertices[0]); const Vec3 lastPoint = worldTM.TransformPoint(volumeInfo.pVertices[volumeInfo.verticesCount - 1]); pRenderAux->DrawLine( lastPoint, Col_SlateBlue, lastPoint + depthOffset, Col_SlateBlue, 2.0f ); pRenderAux->DrawLine( lastPoint + depthOffset, Col_SlateBlue, firstPoint + depthOffset, Col_SlateBlue, 2.0f ); }
void CDeflectorShield::ProcessProjectile(CProjectile* pProjectile, Vec3 hitPosition, Vec3 hitNormal, Vec3 hitDirection) { if (CanProjectilePassThroughShield(pProjectile)) { return; } const Matrix34& intoWorldTransform = GetEntity()->GetWorldTM(); Matrix34 intoLocalTransform = intoWorldTransform.GetInvertedFast(); SDeflectedEnergy deflectedEnergy; deflectedEnergy.m_delay = 0.0f; deflectedEnergy.m_localPosition = intoLocalTransform.TransformPoint(hitPosition); deflectedEnergy.m_localDirection = intoLocalTransform.TransformVector(-hitDirection); deflectedEnergy.m_damage = CLAMP(pProjectile->GetDamage(), m_minDamage, m_maxDamage); if (deflectedEnergy.m_localDirection.NormalizeSafe() > 0.0f) { m_deflectedEnergies.push_back(deflectedEnergy); GetGameObject()->EnableUpdateSlot(this, 0); } if (m_pDeflectedEffect) { m_pDeflectedEffect->Spawn(IParticleEffect::ParticleLoc(hitPosition, hitNormal)); } pProjectile->Destroy(); }
bool CBurst::CBurstFiringLocator::GetFiringPos(EntityId weaponId, const IFireMode* pFireMode, Vec3& pos) { if (!HasValidFiringLocator()) return false; Matrix34 fireHelperLocation = GetFiringLocatorTM(); Vec3 right = fireHelperLocation.GetColumn0(); pos = fireHelperLocation.TransformPoint(Vec3(ZERO)) + (right*(float)m_pBurst->m_burst_shot*0.1f - right*0.35f); return true; }
bool CJaw::GetFiringPos(EntityId weaponId, const IFireMode* pFireMode, Vec3& pos) { int slot = eIGS_ThirdPerson; CActor* pOwnerActor = GetOwnerActor(); if (pOwnerActor && !pOwnerActor->IsThirdPerson()) slot = eIGS_FirstPerson; ICharacterInstance *pCharacter = GetEntity()->GetCharacter(slot); if (!pCharacter || !(pCharacter->IsCharacterVisible() && slot==eIGS_ThirdPerson)) return false; Matrix34 fireHelperLocation = GetCharacterAttachmentWorldTM(slot, "muzzleflash_effect"); pos = fireHelperLocation.TransformPoint(Vec3(ZERO)); return true; }
void CVehiclePartWaterRipplesGenerator::Update(const float frameTime) { //IVehicleMovement* pMovement = m_pVehicle->GetMovement(); const SVehicleStatus& status = m_pVehicle->GetStatus(); const bool movingFastEnough = (status.speed > m_minMovementSpeed); if (movingFastEnough) { const Matrix34 vehicleWorldTM = m_pVehicle->GetEntity()->GetWorldTM(); // Check if moving backwards... if (m_onlyMovingForward) { const float dotProduct = vehicleWorldTM.GetColumn1().Dot((status.vel / status.speed)); if (dotProduct < 0.0f) return; } gEnv->pRenderer->EF_AddWaterSimHit( vehicleWorldTM.TransformPoint( m_localOffset ), m_waterRipplesScale, m_waterRipplesStrength ); } }
bool CIntersectionAssistanceUnit::TestForIntersectionAtLocation(const eTestMethod testMethod, const Matrix34& wMat, EntityId testEntityId, EntityId ignoreEnt, QuatT& outAdjustedResult, const bool bCentreOnFocalEnt /* = false */, bool bRenderOnFail /* = true */, const int index /* = -1*/) { // Build an OOBB that surrounds this entity, test for intersection between that and world IEntity* pEntity = gEnv->pEntitySystem->GetEntity(testEntityId); if(pEntity) { IPhysicalEntity* pPhysical = pEntity->GetPhysics(); if(pPhysical) { OBB entOBB; AABB entAABB; pEntity->GetLocalBounds(entAABB); entOBB.SetOBBfromAABB(Quat(IDENTITY), entAABB); // Do Primitive world intersection primitives::box physBox; physBox.bOriented = 1; // LSpace physBox.center = entOBB.c; physBox.Basis = entOBB.m33; physBox.size.x = entOBB.h.x; physBox.size.y = entOBB.h.y; physBox.size.z = entOBB.h.z; // WSpace physBox.center = wMat.TransformPoint(physBox.center); physBox.Basis *= Matrix33(wMat).GetInverted(); // Optional tweak - We can get away with a little bit of scaling down (if edges are slightly embedded the physics pushes them out easily) physBox.size = physBox.size.scale(kPhysBoxScaleFactor); // adjust Vec3 vAdjustments(0.0f,0.0f,0.0f); if(bCentreOnFocalEnt && m_focalEntityId) { Vec3 vDesiredPos = CalculateTargetAdjustPoint(pEntity, wMat, physBox.center); vAdjustments = (vDesiredPos - physBox.center); physBox.center += vAdjustments; } IEntity* pIgnoreEnt = gEnv->pEntitySystem->GetEntity(ignoreEnt); IPhysicalEntity* pIgnorePhys = pIgnoreEnt ? pIgnoreEnt->GetPhysics() : NULL; // Test if(testMethod == eTM_Immediate #ifndef _RELEASE || g_pGameCVars->pl_pickAndThrow.intersectionAssistDebugEnabled >= 1 #endif // #ifndef _RELEASE ) { geom_contact *contacts; intersection_params params; float numHits = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(primitives::box::type, &physBox, Vec3(ZERO), ent_static|ent_terrain, &contacts, 0, 3, ¶ms, 0, 0, &pIgnorePhys, pIgnorePhys ? 1 : 0); // Debug #ifndef _RELEASE if(g_pGameCVars->pl_pickAndThrow.intersectionAssistDebugEnabled) { const bool bIntersect = numHits <= 0.0f ? false : true; if(bRenderOnFail || !bIntersect) { const ColorB colorPositive = ColorB(16, 96, 16); const ColorB colorNegative = ColorB(128, 0, 0); const ColorB colorSelected = ColorB(0,255,0); if(numHits > 0.0f) { gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(contacts->pt, 0.1f, colorPositive); } OBB finalOBB; finalOBB.SetOBB(Matrix33(IDENTITY), physBox.size, Vec3(0.0f,0.0f,0.0f)); Matrix34 drawMat = wMat; drawMat.AddTranslation(physBox.center - wMat.GetTranslation()); if(index != -1 && index == m_currentBestIndex) { gEnv->pRenderer->GetIRenderAuxGeom()->DrawOBB(finalOBB, drawMat, false, colorSelected, eBBD_Faceted); } else { gEnv->pRenderer->GetIRenderAuxGeom()->DrawOBB(finalOBB, drawMat, false, bIntersect ? colorNegative : colorPositive, eBBD_Faceted); } } } #endif //#ifndef RELEASE // If we performed an adjust, make sure we pass out the QuatT representing the FINAL ENTITY POSITION that passed/failed (not the phys box etc) outAdjustedResult.t = wMat.GetTranslation() + vAdjustments; outAdjustedResult.q = Quat(wMat); #ifndef _RELEASE // allow optional debug drawing of last known good positions by retaining non adjusted position if(g_pGameCVars->pl_pickAndThrow.intersectionAssistDebugEnabled == 1) { outAdjustedResult.t = wMat.GetTranslation(); } #endif // #ifndef _RELEASE return (numHits > 0.0f); } else { // QUEUE primitive intersection check outAdjustedResult.t = wMat.GetTranslation() + vAdjustments; outAdjustedResult.q = Quat(wMat); CRY_ASSERT(index >= 0); m_intersectionTester.DoCheck(index,physBox,outAdjustedResult,pIgnorePhys); return false; } } } return false; }
virtual void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo ) { if (!pActInfo->pEntity) return; if (event == eFE_Activate && IsPortActive(pActInfo, IN_ACTIVATE)) { pe_action_impulse action; int ipart = GetPortInt( pActInfo, IN_PARTINDEX ); if (ipart>0) action.ipart = ipart-1; IEntity* pEntity = pActInfo->pEntity; ECoordSys coordSys = (ECoordSys)GetPortInt( pActInfo, IN_COORDSYS ); if (coordSys==CS_PARENT && !pEntity->GetParent()) coordSys = CS_WORLD; // When a "zero point" is set in the node, the value is left undefined and physics assume it is the CM of the object. // but when the entity has a parent (is linked), then we have to use a real world coordinate for the point, because we have to apply the impulse to the highest entity // on the hierarchy and physics will use the position of that entity instead of the position of the entity assigned to the node bool bHaveToUseTransformedZeroPoint = false; Vec3 transformedZeroPoint; Matrix34 transMat; switch (coordSys) { case CS_WORLD: default: { transMat.SetIdentity(); bHaveToUseTransformedZeroPoint = pEntity->GetParent()!=NULL; transformedZeroPoint = pEntity->GetWorldPos(); break; } case CS_PARENT: { transMat = pEntity->GetParent()->GetWorldTM(); bHaveToUseTransformedZeroPoint = pEntity->GetParent()->GetParent()!=NULL; transformedZeroPoint = pEntity->GetParent()->GetWorldPos(); break; } case CS_LOCAL: { transMat = pEntity->GetWorldTM(); bHaveToUseTransformedZeroPoint = pEntity->GetParent()!=NULL; transformedZeroPoint = pEntity->GetWorldPos(); break; } } action.impulse = GetPortVec3( pActInfo, IN_IMPULSE ); action.impulse = transMat.TransformVector( action.impulse ); Vec3 angImpulse = GetPortVec3( pActInfo, IN_ANGIMPULSE ); if (!angImpulse.IsZero()) action.angImpulse = transMat.TransformVector( angImpulse ); Vec3 pointApplication = GetPortVec3( pActInfo, IN_POINT ); if (!pointApplication.IsZero()) action.point = transMat.TransformPoint( pointApplication ); else { if (bHaveToUseTransformedZeroPoint) action.point = transformedZeroPoint; } // the impulse has to be applied to the highest entity in the hierarchy. This comes from how physics manage linked entities. IEntity* pEntityImpulse = pEntity; while (pEntityImpulse->GetParent()) { pEntityImpulse = pEntityImpulse->GetParent(); } IPhysicalEntity * pPhysEntity = pEntityImpulse->GetPhysics(); if (pPhysEntity) pPhysEntity->Action( &action ); } }
//------------------------------------------------------------------ void CLam::UpdateTPLaser(float frameTime, CItem* parent) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); const int frameId = gEnv->pRenderer->GetFrameID(); if (s_lastUpdateFrameId != frameId) { // Check how many LAMs to update this frame. float dt = frameTime; // + s_laserUpdateTimeError; const int n = s_lasers.size(); int nActive = 0; for (int i = 0; i < n; ++i) { if (!s_lasers[i]->IsLaserActivated() && !s_lasers[i]->IsLightActivated()) continue; nActive++; } float updatedPerSecond = (nActive / LASER_UPDATE_TIME) + s_laserUpdateTimeError; int updateCount = (int)floorf(updatedPerSecond * dt); if(dt==0.0f) s_laserUpdateTimeError = 0.0f; else s_laserUpdateTimeError = updatedPerSecond - updateCount/dt; s_curLaser %= n; for (int i = 0, j = 0; i < n && j < updateCount ; ++i) { s_curLaser = (s_curLaser + 1) % n; if (!s_lasers[s_curLaser]->IsLaserActivated() && !s_lasers[s_curLaser]->IsLightActivated()) continue; s_lasers[s_curLaser]->SetAllowUpdate(); ++j; } s_lastUpdateFrameId = frameId; } IEntity* pRootEnt = GetEntity(); if (!pRootEnt) return; IEntity *pLaserEntity = m_pEntitySystem->GetEntity(m_pLaserEntityId); // if(!pLaserEntity) // return; const CCamera& camera = gEnv->pRenderer->GetCamera(); Vec3 lamPos = pRootEnt->GetWorldPos(); //pLaserEntity->GetParent()->GetWorldPos(); Vec3 dir = pRootEnt->GetWorldRotation().GetColumn1(); //pLaserEntity->GetParent()->GetWorldRotation().GetColumn1(); bool charNotVisible = false; float dsg1Scale = 1.0f; //If character not visible, laser is not correctly updated if(parent) { if(CActor* pOwner = parent->GetOwnerActor()) { ICharacterInstance* pCharacter = pOwner->GetEntity()->GetCharacter(0); if(pCharacter && !pCharacter->IsCharacterVisible()) charNotVisible = true; } if(parent->GetEntity()->GetClass()==CItem::sDSG1Class) dsg1Scale = 3.0f; } // if (!pLaserEntity->GetParent()) // return; Vec3 hitPos(0,0,0); float laserLength = 0.0f; // HACK??: Use player movement controller locations, or else the laser // pops all over the place when character out of the screen. CActor *pActor = parent->GetOwnerActor(); if (pActor && (!pActor->IsPlayer() || charNotVisible)) { if (IMovementController* pMC = pActor->GetMovementController()) { SMovementState state; pMC->GetMovementState(state); if(!charNotVisible) lamPos = state.weaponPosition; else { float oldZPos = lamPos.z; lamPos = state.weaponPosition; if(m_lastZPos>0.0f) lamPos.z = m_lastZPos; //Stabilize somehow z position (even if not accurate) else lamPos.z = oldZPos; } const float angleMin = DEG2RAD(3.0f); const float angleMax = DEG2RAD(7.0f); const float thr = cosf(angleMax); float dot = dir.Dot(state.aimDirection); if (dot > thr) { float a = acos_tpl(dot); float u = 1.0f - clamp((a - angleMin) / (angleMax - angleMin), 0.0f, 1.0f); dir = dir + u * (state.aimDirection - dir); dir.Normalize(); } } } if(!charNotVisible) m_lastZPos = lamPos.z; lamPos += (dir*0.10f); if (m_allowUpdate) { m_allowUpdate = false; IPhysicalEntity* pSkipEntity = NULL; if(parent->GetOwner()) pSkipEntity = parent->GetOwner()->GetPhysics(); const float range = m_lamparams.laser_range[eIGS_ThirdPerson]*dsg1Scale; // Use the same flags as the AI system uses for visbility. const int objects = ent_terrain|ent_static|ent_rigid|ent_sleeping_rigid|ent_independent; //ent_living; const int flags = (geom_colltype_ray << rwi_colltype_bit) | rwi_colltype_any | (10 & rwi_pierceability_mask) | (geom_colltype14 << rwi_colltype_bit); ray_hit hit; if (gEnv->pPhysicalWorld->RayWorldIntersection(lamPos, dir*range, objects, flags, &hit, 1, &pSkipEntity, pSkipEntity ? 1 : 0)) { laserLength = hit.dist; m_lastLaserHitPt = hit.pt; m_lastLaserHitSolid = true; } else { m_lastLaserHitSolid = false; m_lastLaserHitPt = lamPos + dir * range; laserLength = range + 0.1f; } // Hit near plane if (dir.Dot(camera.GetViewdir()) < 0.0f) { Plane nearPlane; nearPlane.SetPlane(camera.GetViewdir(), camera.GetPosition()); nearPlane.d -= camera.GetNearPlane()+0.15f; Ray ray(lamPos, dir); Vec3 out; m_lastLaserHitViewPlane = false; if (Intersect::Ray_Plane(ray, nearPlane, out)) { float dist = Distance::Point_Point(lamPos, out); if (dist < laserLength) { laserLength = dist; m_lastLaserHitPt = out; m_lastLaserHitSolid = true; m_lastLaserHitViewPlane = true; } } } hitPos = m_lastLaserHitPt; } else { laserLength = Distance::Point_Point(m_lastLaserHitPt, lamPos); hitPos = lamPos + dir * laserLength; } if (m_smoothLaserLength < 0.0f) m_smoothLaserLength = laserLength; else { if (laserLength < m_smoothLaserLength) m_smoothLaserLength = laserLength; else m_smoothLaserLength += (laserLength - m_smoothLaserLength) * min(1.0f, 10.0f * frameTime); } float laserAIRange = 0.0f; if (m_laserActivated && pLaserEntity) { // Orient the laser towards the point point. Matrix34 parentTMInv; parentTMInv = pRootEnt->GetWorldTM().GetInverted(); Vec3 localDir = parentTMInv.TransformPoint(hitPos); float finalLaserLen = localDir.NormalizeSafe(); Matrix33 rot; rot.SetIdentity(); rot.SetRotationVDir(localDir); pLaserEntity->SetLocalTM(rot); laserAIRange = finalLaserLen; const float assetLength = 2.0f; finalLaserLen = CLAMP(finalLaserLen,0.01f,m_lamparams.laser_max_len*dsg1Scale); float scale = finalLaserLen / assetLength; // Scale the laser based on the distance. if (m_laserEffectSlot >= 0) { Matrix33 scl; scl.SetIdentity(); scl.SetScale(Vec3(1,scale,1)); pLaserEntity->SetSlotLocalTM(m_laserEffectSlot, scl); } if (m_dotEffectSlot >= 0) { if (m_lastLaserHitSolid) { Matrix34 mt = Matrix34::CreateTranslationMat(Vec3(0,finalLaserLen,0)); if(m_lastLaserHitViewPlane) mt.Scale(Vec3(0.2f,0.2f,0.2f)); pLaserEntity->SetSlotLocalTM(m_dotEffectSlot, mt); } else { Matrix34 scaleMatrix; scaleMatrix.SetIdentity(); scaleMatrix.SetScale(Vec3(0.001f,0.001f,0.001f)); pLaserEntity->SetSlotLocalTM(m_dotEffectSlot, scaleMatrix); } } } float lightAIRange = 0.0f; if (m_lightActivated) { float range = clamp(m_smoothLaserLength, 0.5f, m_lamparams.light_range[eIGS_ThirdPerson]); lightAIRange = range * 1.5f; if (m_lightID[eIGS_ThirdPerson] && m_smoothLaserLength > 0.0f) { CItem* pLightEffect = this; if (IItem *pOwnerItem = m_pItemSystem->GetItem(GetParentId())) pLightEffect = (CItem *)pOwnerItem; pLightEffect->SetLightRadius(range, m_lightID[eIGS_ThirdPerson]); } } if (laserAIRange > 0.0001f || lightAIRange > 0.0001f) UpdateAILightAndLaser(lamPos, dir, lightAIRange, m_lamparams.light_fov[eIGS_ThirdPerson], laserAIRange); }
void CVehicleWeaponControlled::Update3PAnim(CPlayer *player, float goalTime, float frameTime, const Matrix34 &mat) { if (player) { if (IEntity *entity = player->GetEntity()) { const float ANIM_ANGLE_RANGE = gf_PI*0.25f; static float dir = 0.05f; static float pos = 0.5f; pos += dir; if (pos > 1.0f) { pos = 1.0f; dir = -dir; } else if (pos < 0.0f) { pos = 0.0f; dir = -dir; } m_CurrentTime = LERP(m_CurrentTime, goalTime, frameTime); if (ICharacterInstance *character = entity->GetCharacter(0)) { ISkeletonAnim *pSkeletonAnim = character->GetISkeletonAnim(); assert(pSkeletonAnim); //Update manually animation time, to match current weapon orientation uint32 numAnimsLayer = pSkeletonAnim->GetNumAnimsInFIFO(0); for(uint32 i=0; i<numAnimsLayer; i++) { CAnimation &animation = pSkeletonAnim->GetAnimFromFIFO(0, i); if (animation.HasStaticFlag( CA_MANUAL_UPDATE )) { float time = m_CurrentTime; //pos; //fmod_tpl(aimRad / ANIM_ANGLE_RANGE, 1.0f); time = (float)__fsel(time, time, 1.0f + time); pSkeletonAnim->SetAnimationNormalizedTime(&animation, time); animation.ClearStaticFlag( CA_DISABLE_MULTILAYER ); } } } const SMountParams* pMountParams = GetMountedParams(); SEntitySlotInfo info; if (GetEntity()->GetSlotInfo(eIGS_ThirdPerson, info)) { if (info.pStatObj) { IStatObj *pStatsObj = info.pStatObj; const Vec3 &leftHandPos = pStatsObj->GetHelperPos(pMountParams->left_hand_helper.c_str()); const Vec3 &rightHandPos = pStatsObj->GetHelperPos(pMountParams->right_hand_helper.c_str()); const Vec3 leftIKPos = mat.TransformPoint(leftHandPos); const Vec3 rightIKPos = mat.TransformPoint(rightHandPos); player->SetIKPos("leftArm", leftIKPos, 1); player->SetIKPos("rightArm", rightIKPos, 1); } } } } }
//----------------------------------------------- //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 CVehicleMovementStdBoat::UpdateSurfaceEffects(const float deltaTime) { FUNCTION_PROFILER( GetISystem(), PROFILE_GAME ); if (0 == g_pGameCVars->v_pa_surface) { ResetParticles(); return; } IEntity* pEntity = m_pVehicle->GetEntity(); const Matrix34& worldTM = pEntity->GetWorldTM(); float distSq = worldTM.GetTranslation().GetSquaredDistance(gEnv->pRenderer->GetCamera().GetPosition()); if (distSq > sqr(300.f) || (distSq > sqr(50.f) && !m_pVehicle->GetGameObject()->IsProbablyVisible())) return; Matrix34 worldTMInv = worldTM.GetInverted(); const SVehicleStatus& status = m_pVehicle->GetStatus(); float velDot = status.vel * worldTM.GetColumn1(); float powerNorm = min(abs(m_movementAction.power), 1.f); SEnvironmentParticles* envParams = m_pPaParams->GetEnvironmentParticles(); SEnvParticleStatus::TEnvEmitters::iterator end = m_paStats.envStats.emitters.end(); for (SEnvParticleStatus::TEnvEmitters::iterator emitterIt = m_paStats.envStats.emitters.begin(); emitterIt!=end; ++emitterIt) { if (emitterIt->layer < 0) { assert(0); continue; } const SEnvironmentLayer& layer = envParams->GetLayer(emitterIt->layer); SEntitySlotInfo info; info.pParticleEmitter = 0; pEntity->GetSlotInfo(emitterIt->slot, info); float countScale = 1.f; float sizeScale = 1.f; float speedScale = 1.f; float speed = 0.f; // check if helper position is beneath water level Vec3 emitterWorldPos = worldTM * emitterIt->quatT.t; float waterLevel = gEnv->p3DEngine->GetWaterLevel(&emitterWorldPos); int matId = 0; if (emitterWorldPos.z <= waterLevel+0.1f && m_physStatus[k_mainThread].submergedFraction<0.999f) { matId = gEnv->pPhysicalWorld->GetWaterMat(); speed = status.speed; bool spray = !strcmp(layer.GetName(), "spray"); if (spray) { // slip based speed -= abs(velDot); } GetParticleScale(layer, speed, powerNorm, countScale, sizeScale, speedScale); } else { countScale = 0.f; } if (matId && matId != emitterIt->matId) { // change effect IParticleEffect* pEff = 0; const char* effect = GetEffectByIndex( matId, layer.GetName() ); if (effect && (pEff = gEnv->pParticleManager->FindEffect(effect))) { #if ENABLE_VEHICLE_DEBUG if (DebugParticles()) CryLog("%s changes water sfx to %s (slot %i)", pEntity->GetName(), effect, emitterIt->slot); #endif if (info.pParticleEmitter) { info.pParticleEmitter->Activate(false); pEntity->FreeSlot(emitterIt->slot); } emitterIt->slot = pEntity->LoadParticleEmitter(emitterIt->slot, pEff); if (emitterIt->slot != -1) pEntity->SetSlotLocalTM(emitterIt->slot, Matrix34(emitterIt->quatT)); info.pParticleEmitter = 0; pEntity->GetSlotInfo(emitterIt->slot, info); } else countScale = 0.f; } if (matId) emitterIt->matId = matId; if (info.pParticleEmitter) { SpawnParams sp; sp.fSizeScale = sizeScale; sp.fCountScale = countScale; sp.fSpeedScale = speedScale; info.pParticleEmitter->SetSpawnParams(sp); if (layer.alignToWater && countScale > 0.f) { Vec3 worldPos(emitterWorldPos.x, emitterWorldPos.y, waterLevel+0.05f); Matrix34 localTM(emitterIt->quatT); localTM.SetTranslation(worldTMInv * worldPos); pEntity->SetSlotLocalTM(emitterIt->slot, localTM); } } #if ENABLE_VEHICLE_DEBUG if (DebugParticles() && m_pVehicle->IsPlayerDriving()) { float color[] = {1,1,1,1}; ColorB red(255,0,0,255); IRenderAuxGeom* pAuxGeom = gEnv->pRenderer->GetIRenderAuxGeom(); const char* effect = info.pParticleEmitter ? info.pParticleEmitter->GetName() : ""; const Matrix34& slotTM = m_pEntity->GetSlotWorldTM(emitterIt->slot); Vec3 ppos = slotTM.GetTranslation(); pAuxGeom->DrawSphere(ppos, 0.2f, red); pAuxGeom->DrawCone(ppos, slotTM.GetColumn1(), 0.1f, 0.5f, red); gEnv->pRenderer->Draw2dLabel(50.f, (float)(400+10*emitterIt->slot), 1.2f, color, false, "<%s> water fx: slot %i [%s], speed %.1f, sizeScale %.2f, countScale %.2f (pos %.0f,%0.f,%0.f)", pEntity->GetName(), emitterIt->slot, effect, speed, sizeScale, countScale, ppos.x, ppos.y, ppos.z); } #endif } // generate water splashes Vec3 wakePos; if(m_pSplashPos) { wakePos = m_pSplashPos->GetWorldSpaceTranslation(); } else { wakePos = worldTM.GetTranslation(); } float wakeWaterLevel = gEnv->p3DEngine->GetWaterLevel(&wakePos); const Vec3& localW = m_localSpeed; if (localW.x >= 0.f) m_diving = false; if (!m_diving && localW.x < -0.03f && status.speed > 10.f && wakePos.z < m_lastWakePos.z && wakeWaterLevel+0.1f >= wakePos.z) { float speedRatio = min(1.f, status.speed/(m_maxSpeed*m_factorMaxSpeed)); m_diving = true; if (m_pWaveEffect) { if (IParticleEmitter* pEmitter = pEntity->GetParticleEmitter(m_wakeSlot)) { pEmitter->Activate(false); pEntity->FreeSlot(m_wakeSlot); m_wakeSlot = -1; } SpawnParams spawnParams; spawnParams.fSizeScale = spawnParams.fCountScale = 0.5f + 0.25f*speedRatio; spawnParams.fSizeScale += 0.4f*m_waveRandomMult; spawnParams.fCountScale += cry_random(0.0f, 0.4f); m_wakeSlot = pEntity->LoadParticleEmitter(m_wakeSlot, m_pWaveEffect, &spawnParams); } // handle splash sound ExecuteTrigger(eSID_Splash); SetSoundParam(eSID_Splash, "intensity", 0.2f*speedRatio + 0.5f*m_waveRandomMult); if (m_rpmPitchDir == 0) { m_rpmPitchDir = -1; m_waveSoundPitch = 0.f; m_waveSoundAmount = 0.02f + m_waveRandomMult*0.08f; } } if (m_wakeSlot != -1) { // update emitter local pos to short above waterlevel Matrix34 tm; if(m_pSplashPos) m_pSplashPos->GetVehicleTM(tm); else tm.SetIdentity(); Vec3 pos = tm.GetTranslation(); pos.z = worldTMInv.TransformPoint(Vec3(wakePos.x,wakePos.y,wakeWaterLevel)).z + 0.2f; tm.SetTranslation(pos); pEntity->SetSlotLocalTM(m_wakeSlot, tm); #if ENABLE_VEHICLE_DEBUG if (IsProfilingMovement()) { Vec3 wPos = worldTM * tm.GetTranslation(); ColorB col(128, 128, 0, 200); gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(wPos, 0.4f, col); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(wPos, col, wPos+Vec3(0,0,1.5f), col); } #endif } m_lastWakePos = wakePos; }
//------------------------------------------------------------------------ void CGunTurret::UpdateOrientation(float deltaTime) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); bool changed = false; bool searching = (m_targetId==0 && m_turretparams.searching); float speed = searching ? m_turretparams.search_speed : m_turretparams.turn_speed; assert(m_goalYaw >= 0.f && m_goalYaw <= gf_PI2); // update turret Matrix34 turretTM = GetEntity()->GetSlotLocalTM(eIGS_Aux0, false); Ang3 turretAngles(turretTM); if(turretAngles.z < 0.0f) turretAngles.z+=gf_PI2; if(cry_fabsf(m_goalYaw-turretAngles.z) > gf_PI) { if(m_goalYaw >= gf_PI) turretAngles.z += gf_PI2; else turretAngles.z -= gf_PI2; } if(m_turretparams.yaw_range < 360.f) { // reverse, to avoid forbidden range if(m_goalYaw > gf_PI && turretAngles.z < gf_PI) turretAngles.z += gf_PI2; else if(m_goalYaw < gf_PI && turretAngles.z > gf_PI) turretAngles.z -= gf_PI2; } if(cry_fabsf(turretAngles.z-m_goalYaw) > 0.001f) { Interp(turretAngles.z, m_goalYaw, speed, deltaTime, 0.25f*speed); if(m_turretSound == INVALID_SOUNDID && gEnv->IsClient()) m_turretSound = PlayAction(g_pItemStrings->turret); changed = true; } else if(m_turretSound != INVALID_SOUNDID) { StopSound(m_turretSound); m_turretSound = INVALID_SOUNDID; } if(changed) { turretTM.SetRotationXYZ(turretAngles,turretTM.GetTranslation()); GetEntity()->SetSlotLocalTM(eIGS_Aux0, turretTM); } // update weapon Matrix34 weaponTM = GetEntity()->GetSlotLocalTM(eIGS_ThirdPerson, false); Ang3 weaponAngles(weaponTM); weaponAngles.z = turretAngles.z; if(cry_fabsf(weaponAngles.x-m_goalPitch) > 0.001f) { Interp(weaponAngles.x, m_goalPitch, speed, deltaTime, 0.25f*speed); if(m_cannonSound == INVALID_SOUNDID && gEnv->IsClient()) m_cannonSound = PlayAction(g_pItemStrings->cannon); changed = true; } else if(m_cannonSound != INVALID_SOUNDID) { StopSound(m_cannonSound); m_cannonSound = INVALID_SOUNDID; } if(changed) { weaponTM.SetRotationXYZ(weaponAngles); Vec3 w_trans = turretTM.TransformPoint(m_radarHelperPos); //Vec3 w_trans = GetSlotHelperPos(eIGS_Aux0,m_radarHelper.c_str(),false); weaponTM.SetTranslation(w_trans); GetEntity()->SetSlotLocalTM(eIGS_ThirdPerson, weaponTM); if(GetEntity()->IsSlotValid(eIGS_Aux1)) { Vec3 b_trans = weaponTM.TransformPoint(m_barrelHelperPos); //Vec3 b_trans = GetSlotHelperPos(eIGS_ThirdPerson,m_barrelHelper.c_str(),false); weaponTM.SetTranslation(b_trans); GetEntity()->SetSlotLocalTM(eIGS_Aux1, weaponTM*m_barrelRotation); } if(gEnv->IsClient()) { for(TEffectInfoMap::const_iterator it=m_effects.begin(); it!=m_effects.end(); ++it) { Matrix34 tm(GetSlotHelperRotation(eIGS_ThirdPerson,it->second.helper.c_str(),true), GetSlotHelperPos(eIGS_ThirdPerson,it->second.helper.c_str(),true)); SetEffectWorldTM(it->first, tm); } } } UpdatePhysics(); if(g_pGameCVars->i_debug_turrets == eGTD_Basic) { DrawDebug(); //gEnv->pRenderer->DrawLabel(GetEntity()->GetWorldPos(), 1.4f, "%s yaw: %.2f, goalYaw: %.2f (%.2f), goalPitch: %.2f (%.2f/%.2f)", searching?"[search]":"", RAD2DEG(turretAngles.z), RAD2DEG(m_goalYaw), 0.5f*(m_turretparams.yaw_range), RAD2DEG(m_goalPitch), m_turretparams.min_pitch, m_turretparams.max_pitch); } }