void CVehicleSeatActionRotateTurret::MaintainPartRotationWorldSpace(EVehicleTurretRotationType eType) { CVehiclePartBase* pPart = m_rotations[eType].m_pPart; IVehiclePart* pParent = pPart->GetParent(); IActor* pActor = m_pSeat->GetPassengerActor(); bool remote = m_pSeat->GetCurrentTransition() == IVehicleSeat::eVT_RemoteUsage; bool worldSpace = m_rotations[eType].m_worldSpace && VehicleCVars().v_independentMountedGuns != 0; if (worldSpace && pParent && pActor && pActor->IsClient() && !remote) { // we want to keep the old worldspace rotation // therefore we're updating the local transform from it // NB: there is no need to clamp here, its done later Matrix34 localTM = pParent->GetWorldTM().GetInverted() * Matrix34(m_rotations[eType].m_prevWorldQuat); localTM.OrthonormalizeFast(); // precision issue const Matrix34 &baseTM = pPart->GetLocalBaseTM(); if (!Matrix34::IsEquivalent(baseTM,localTM)) { Ang3 anglesCurr(baseTM); Ang3 angles(localTM); if (eType == eVTRT_Pitch) { angles.y = anglesCurr.y; angles.z = anglesCurr.z; } else if (eType == eVTRT_Yaw) { angles.x = anglesCurr.x; angles.y = anglesCurr.y; } localTM.SetRotationXYZ(angles); localTM.SetTranslation(baseTM.GetTranslation()); pPart->SetLocalBaseTM(localTM); m_pSeat->ChangedNetworkState(CVehicle::ASPECT_PART_MATRIX); } #if ENABLE_VEHICLE_DEBUG if (VehicleCVars().v_debugdraw == eVDB_Parts) { float color[] = {1,1,1,1}; Ang3 a(localTM), aBase(baseTM); gEnv->pRenderer->Draw2dLabel(200,200,1.4f,color,false,"localAng: %.1f (real: %.1f)", RAD2DEG(a.z), RAD2DEG(aBase.z)); } #endif } }
//------------------------------------------------------------------------ void CVehicleHelper::GetVehicleTM(Matrix34& vehicleTM, bool forced) const { vehicleTM = m_localTM; IVehiclePart* pParent = m_pParentPart; while (pParent) { vehicleTM = pParent->GetLocalTM(true, forced) * vehicleTM; pParent = pParent->GetParent(); } }
void CVehicleWeaponPulseC::Update(SEntityUpdateContext& ctx, int update) { if(!m_vehicleId && GetEntity()->GetParent()) { m_vehicleId = GetEntity()->GetParent()->GetId(); CRY_ASSERT(gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(m_vehicleId) && "Using VehicleWeapons on non-vehicles may lead to unexpected behavior."); } IVehicle* pVehicle = GetVehicle(); if(pVehicle) { IVehiclePart* pPart = pVehicle->GetWeaponParentPart(GetEntityId()); if(pPart) { const Matrix34& partWorldTM = pPart->GetWorldTM(); const Vec3 partDirection = partWorldTM.GetColumn1(); const Vec3 partPosition = partWorldTM.GetTranslation(); //ColorB col(255, 0, 0); //gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(partPosition, col, partPosition + 100.0f * partDirection, col, 2.0f); //ok, ok, i'll optimise this later Matrix34 mat = pVehicle->GetEntity()->GetWorldTM(); Matrix33 matO(mat); matO.Invert(); const Vec3 diff = (m_TargetPos - partPosition).GetNormalized(); m_destination.SetLerp(partDirection, diff, ctx.fFrameTime); Quat quat1; //quat1.SetRotationVDir(diff, 0.0f); quat1.SetRotationVDir(m_destination.GetNormalized(), 0.0f); Matrix33 mat2(quat1); mat2 = matO * mat2; m_destination = m_destination * 10000.0f + partPosition; m_targetPosition = m_destination; m_aimPosition = m_destination; pPart->SetLocalTM(Matrix34(mat2, pPart->GetLocalTM(true, true).GetTranslation())); } } Base::Update(ctx, update); }
//------------------------------------------------------------------------ bool CVehicleSeatActionRotateTurret::GetRemainingAnglesToAimGoalInDegrees(float &pitch, float &yaw) { // no aim goal set (or it got cleared)? if (m_aimGoal.IsZero()) { return false; // have no aim goal } IVehiclePart* pPitchPart = m_rotations[eVTRT_Pitch].m_pPart; IVehiclePart* pYawPart = m_rotations[eVTRT_Yaw].m_pPart; if (!pYawPart) { pitch = yaw = 0.0f; return true; // have an aim goal } // aim goal is a world pos. Convert it to vehicle space: Vec3 aimGoalLocal = m_pVehicle->GetEntity()->GetWorldTM().GetInverted() * m_aimGoal; // direction from yaw part pivot to aim goal Vec3 yawPartToAimGoal = aimGoalLocal - pYawPart->GetLocalTM(false).GetTranslation(); // angles from yaw part to aim goal Quat aimDir = Quat::CreateRotationVDir(yawPartToAimGoal.GetNormalizedSafe()); Ang3 desiredAngles(aimDir); if (pPitchPart) { Ang3 pitchAngles(pPitchPart->GetLocalTM(false)); pitch = RAD2DEG(desiredAngles.x - pitchAngles.x); pitch = fmod(pitch, 360.0f); } else { pitch = 0.0f; } Ang3 yawAngles(pYawPart->GetLocalTM(false)); yaw = RAD2DEG(desiredAngles.z - yawAngles.z); yaw = fmod(yaw, 360.0f); return true; // have an aim goal }
//------------------------------------------------------------------------ void CVehicleSeatActionRotateTurret::UpdateAimGoal() { Vec3 aimGoalLocal = m_pVehicle->GetEntity()->GetWorldTM().GetInverted() * m_aimGoal; IVehiclePart* pPitchPart = m_rotations[eVTRT_Pitch].m_pPart; if (pPitchPart) { Vec3 pitchPartToAimGoal = aimGoalLocal - pPitchPart->GetLocalTM(false).GetTranslation(); Quat pitchAimDir = Quat::CreateRotationVDir(pitchPartToAimGoal.GetNormalizedSafe()); Ang3 desiredPitchAngles(pitchAimDir); Ang3 currentPitchAngles(pPitchPart->GetLocalTM(false)); m_rotations[eVTRT_Pitch].m_action = desiredPitchAngles.x - currentPitchAngles.x; } IVehiclePart* pYawPart = m_rotations[eVTRT_Yaw].m_pPart; if (pYawPart) { Vec3 yawPartToAimGoal = aimGoalLocal - pYawPart->GetLocalTM(false).GetTranslation(); Quat yawAimDir = Quat::CreateRotationVDir(yawPartToAimGoal.GetNormalizedSafe()); Ang3 desiredYawAngles(yawAimDir); Ang3 currentYawAngles(pYawPart->GetLocalTM(false)); m_rotations[eVTRT_Yaw].m_action = fmod(desiredYawAngles.z - currentYawAngles.z + 3.0f * gf_PI, gf_PI2) - gf_PI; } }
//------------------------------------------------------------------------ void CVehicleMovementTank::PostInit() { CVehicleMovementStdWheeled::PostInit(); for (size_t i=0; i<m_wheelParts.size(); ++i) { if (m_wheelParts[i]->GetIWheel()->GetCarGeomParams()->bDriving) m_drivingWheels[m_wheelParts[i]->GetLocalTM(false).GetTranslation().x > 0.f] = m_wheelParts[i]; } assert(m_drivingWheels[0] && m_drivingWheels[1]); m_treadParts.clear(); int nParts = m_pVehicle->GetPartCount(); for (int i=0; i<nParts; ++i) { IVehiclePart* pPart = m_pVehicle->GetPart(i); if (pPart->GetType() == IVehiclePart::eVPT_Tread) { m_treadParts.push_back(pPart); } } }
void CVehicleMovementMPVTOL::PostInit() { BaseClass::PostInit(); for (int i = 0; i < m_pVehicle->GetPartCount(); i++) { IVehiclePart* pPart = m_pVehicle->GetPart(i); if (m_pLeftWing == NULL && strcmpi(pPart->GetName(), "wing_left_pivot") == 0) { m_pLeftWing = pPart; pPart->SetMoveable(); m_pVehicle->SetObjectUpdate(pPart, IVehicle::eVOU_AlwaysUpdate); } else if(m_pRightWing == NULL && strcmpi(pPart->GetName(), "wing_right_pivot") == 0) { m_pRightWing = pPart; pPart->SetMoveable(); m_pVehicle->SetObjectUpdate(pPart, IVehicle::eVOU_AlwaysUpdate); } } CRY_ASSERT_MESSAGE(m_pLeftWing && m_pRightWing, "CVehicleMovementMPVTOL::PostInit - Wing parts not found"); }
//------------------------------------------------------------------------ void CVehicleDamageBehaviorBlowTire::Activate(bool activate) { if (activate == m_isActive) return; if (activate && m_pVehicle->IsDestroyed()) return; if (activate) { // NOTE: stance and physics position when getting into vehicles is set wrong if (!gEnv->pSystem->IsSerializingFile()) DamagePlayers(); } IVehicleComponent* pComponent = m_pVehicle->GetComponent(m_component.c_str()); if (!pComponent) return; IVehiclePart* pPart = pComponent->GetPart(0); if (!pPart) return; // if IVehicleWheel available, execute full damage behavior. if null, only apply effects IVehicleWheel* pWheel = pPart->GetIWheel(); if (activate) { IEntity* pEntity = m_pVehicle->GetEntity(); IPhysicalEntity* pPhysics = pEntity->GetPhysics(); const Matrix34& wheelTM = pPart->GetLocalTM(false); const SVehicleStatus& status = m_pVehicle->GetStatus(); if (pWheel) { const pe_cargeomparams* pParams = pWheel->GetCarGeomParams(); // handle destroyed wheel pe_params_wheel wheelParams; wheelParams.iWheel = pWheel->GetWheelIndex(); wheelParams.minFriction = wheelParams.maxFriction = 0.5f * pParams->maxFriction; pPhysics->SetParams(&wheelParams); if (IVehicleMovement* pMovement = m_pVehicle->GetMovement()) { SVehicleMovementEventParams params; params.pComponent = pComponent; params.iValue = pWheel->GetWheelIndex(); pMovement->OnEvent(IVehicleMovement::eVME_TireBlown, params); } if (status.speed > 0.1f) { // add angular impulse pe_action_impulse angImp; float amount = m_pVehicle->GetMass() * status.speed * Random(0.25f, 0.45f) * -sgn(wheelTM.GetTranslation().x); angImp.angImpulse = pEntity->GetWorldTM().TransformVector(Vec3(0,0,amount)); pPhysics->Action(&angImp); } m_aiImmobilizedTimer = m_pVehicle->SetTimer(-1, AI_IMMOBILIZED_TIME*1000, this); } if (!gEnv->pSystem->IsSerializingFile()) { // add linear impulse pe_action_impulse imp; imp.point = pPart->GetWorldTM().GetTranslation(); float amount = m_pVehicle->GetMass() * Random(0.1f, 0.15f); if (pWheel) { amount *= max(0.5f, min(10.f, status.speed)); if (status.speed < 0.1f) amount = -0.5f*amount; } else amount *= 0.5f; imp.impulse = pEntity->GetWorldTM().TransformVector(Vec3(0,0,amount)); pPhysics->Action(&imp); // effect IParticleEffect* pEffect = gEnv->pParticleManager->FindEffect(TIRE_BLOW_EFFECT); if (pEffect) { int slot = pEntity->LoadParticleEmitter(-1, pEffect); if (slot > -1) { float rotation = pWheel ? 0.5f * gf_PI * -sgn(wheelTM.GetTranslation().x) : gf_PI; Matrix34 tm = Matrix34::CreateRotationZ(rotation); tm.SetTranslation(wheelTM.GetTranslation()); pEntity->SetSlotLocalTM(slot, tm); } } // remove affected decals { Vec3 pos = pPart->GetWorldTM().GetTranslation(); AABB aabb = pPart->GetLocalBounds(); float radius = aabb.GetRadius(); Vec3 vRadius(radius,radius,radius); AABB areaBox(pos-vRadius, pos+vRadius); IRenderNode * pRenderNode = NULL; if (IEntityRenderProxy *pRenderProxy = (IEntityRenderProxy*)pEntity->GetProxy(ENTITY_PROXY_RENDER)) pRenderNode = pRenderProxy->GetRenderNode(); gEnv->p3DEngine->DeleteDecalsInRange(&areaBox, pRenderNode); } } } else { if (pWheel) { // restore wheel properties IPhysicalEntity* pPhysics = m_pVehicle->GetEntity()->GetPhysics(); pe_params_wheel wheelParams; for (int i=0; i<m_pVehicle->GetWheelCount(); ++i) { const pe_cargeomparams* pParams = m_pVehicle->GetWheelPart(i)->GetIWheel()->GetCarGeomParams(); wheelParams.iWheel = i; wheelParams.bBlocked = 0; wheelParams.suspLenMax = pParams->lenMax; wheelParams.bDriving = pParams->bDriving; wheelParams.minFriction = pParams->minFriction; wheelParams.maxFriction = pParams->maxFriction; pPhysics->SetParams(&wheelParams); } if (IVehicleMovement* pMovement = m_pVehicle->GetMovement()) { SVehicleMovementEventParams params; params.pComponent = pComponent; params.iValue = pWheel->GetWheelIndex(); // reset the particle status pMovement->OnEvent(IVehicleMovement::eVME_TireRestored, params); } } m_aiImmobilizedTimer = -1; } m_isActive = activate; }
//------------------------------------------------------------------------ bool CVehiclePartAnimated::ChangeState(EVehiclePartState state, int flags) { if ((state == eVGS_Default) && m_initialiseOnChangeState) { // Initialise! // Having to do this because of the way the glass code // swaps a cstatobj. The way the vehicle code stores its // statobj in m_intactStatObjs is going to need reviewing if (m_pCharInstance) { ISkeletonPose* pSkeletonPose = m_pCharInstance->GetISkeletonPose(); IDefaultSkeleton &rIDefaultSkeleton = m_pCharInstance->GetIDefaultSkeleton(); ISkeletonPose* pSkeletonPoseDestroyed = m_pCharInstanceDestroyed ? m_pCharInstanceDestroyed->GetISkeletonPose() : NULL; IDefaultSkeleton* pICharacterModelSkeletonDestroyed = m_pCharInstanceDestroyed ? &m_pCharInstanceDestroyed->GetIDefaultSkeleton() : NULL; if (pSkeletonPose) { const bool bDestroyedSkelExists = pSkeletonPoseDestroyed && pICharacterModelSkeletonDestroyed; for (uint32 i = 0; i < rIDefaultSkeleton.GetJointCount(); i++) { if (IStatObj* pStatObjIntact = pSkeletonPose->GetStatObjOnJoint(i)) { const char* jointName = rIDefaultSkeleton.GetJointNameByID(i); if (m_intactStatObjs.find(CONST_TEMP_STRING(jointName)) == m_intactStatObjs.end()) { m_intactStatObjs.insert(TStringStatObjMap::value_type(jointName, pStatObjIntact)); } // tell the streaming engine to stream destroyed version together with non destroyed if (bDestroyedSkelExists && i < pICharacterModelSkeletonDestroyed->GetJointCount()) { if (IStatObj* pStatObjIntactDestroyed = pSkeletonPoseDestroyed->GetStatObjOnJoint(i)) { pStatObjIntact->SetStreamingDependencyFilePath(pStatObjIntactDestroyed->GetFilePath()); } } } } } } m_initialiseOnChangeState = false; } bool change = CVehiclePartBase::ChangeState(state, flags); if (state == eVGS_Default && !change) { // need to restore state if one of the children is in higher state EVehiclePartState maxState = GetMaxState(); if (maxState > m_state) change = true; } if (!change) { return false; } if (state == eVGS_Destroyed) { if (m_ignoreDestroyedState) return false; if (m_pCharInstance && m_pCharInstanceDestroyed) { ISkeletonPose* pSkeletonPose = m_pCharInstance->GetISkeletonPose(); IDefaultSkeleton &rIDefaultSkeleton = m_pCharInstance->GetIDefaultSkeleton(); if (pSkeletonPose) { IMaterial* pDestroyedMaterial = m_pVehicle->GetDestroyedMaterial(); for (uint32 i = 0; i < rIDefaultSkeleton.GetJointCount(); i++) { if (IStatObj* pStatObjIntact = pSkeletonPose->GetStatObjOnJoint(i)) { const char* jointName = rIDefaultSkeleton.GetJointNameByID(i); IStatObj* pStatObj = GetDestroyedGeometry(jointName); // sets new StatObj to joint, if null, removes it. // object whose name includes "proxy" are not removed. if (pStatObj || !strstr(jointName, "proxy")) { SetCGASlot(i, pStatObj); if (pStatObj && !pDestroyedMaterial) { if (IMaterial* pMaterial = pStatObj->GetMaterial()) SetMaterial(pMaterial); } #if ENABLE_VEHICLE_DEBUG if (IsDebugParts()) { CryLog("swapping StatObj on joint %u (%s) -> %s", i, jointName, pStatObj ? pStatObj->GetGeoName() : "<NULL>"); } #endif } } } FlagSkeleton(pSkeletonPose, rIDefaultSkeleton); for (TStringVehiclePartMap::iterator ite = m_jointParts.begin(); ite != m_jointParts.end(); ++ite) { IVehiclePart* pPart = ite->second; pPart->ChangeState(state, flags | eVPSF_Physicalize); } CryCharAnimationParams animParams; animParams.m_nFlags |= CA_LOOP_ANIMATION; // pSkeleton->SetRedirectToLayer0(1); // pSkeleton->StartAnimation("Default",0, 0,0, animParams); // [MR: commented out on Ivos request] if (pDestroyedMaterial) { SetMaterial(pDestroyedMaterial); } } } } else if (state == eVGS_Default) { if (m_pCharInstance && m_pCharInstanceDestroyed) { // reset material (in case we replaced it with the destroyed material) IMaterial* pMaterial = m_pVehicle->GetPaintMaterial(); if (!pMaterial) { // no paint, so revert to the material already set on the character pMaterial = m_pCharInstance->GetIMaterial(); } if (pMaterial) { SetMaterial(pMaterial); } IDefaultSkeleton &rIDefaultSkeleton = m_pCharInstance->GetIDefaultSkeleton(); { for (TStringStatObjMap::iterator ite = m_intactStatObjs.begin(); ite != m_intactStatObjs.end(); ++ite) { const string &jointName = ite->first; IStatObj* pStatObj = ite->second; int16 jointId = rIDefaultSkeleton.GetJointIDByName(jointName.c_str()); if (jointId > -1) { // if compound StatObj (from deformation), use first SubObj for restoring if (pStatObj != NULL) { if (!pStatObj->GetRenderMesh() && pStatObj->GetSubObjectCount() > 0) { pStatObj = pStatObj->GetSubObject(0)->pStatObj; } SetCGASlot(jointId, pStatObj); #if ENABLE_VEHICLE_DEBUG if (IsDebugParts()) CryLog("restoring StatObj on joint %i (%s) -> %s", jointId, jointName.c_str(), pStatObj ? pStatObj->GetGeoName() : "<NULL>"); #endif } TStringVehiclePartMap::iterator it = m_jointParts.find(jointName); if (it != m_jointParts.end()) { it->second->ChangeState(state, flags & ~eVPSF_Physicalize | eVPSF_Force); } } } flags |= eVPSF_Physicalize; } } } m_state = state; // physicalize after all parts have been restored if (flags & eVPSF_Physicalize && GetEntity()->GetPhysics()) { Physicalize(); for (TStringVehiclePartMap::iterator it = m_jointParts.begin(); it != m_jointParts.end(); ++it) { it->second->Physicalize(); } } return true; }
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); }
//------------------------------------------------------------------------ bool CVehicleMovementStdBoat::Init(IVehicle* pVehicle, const CVehicleParams& table) { if (!CVehicleMovementBase::Init(pVehicle, table)) return false; MOVEMENT_VALUE("velMax", m_velMax); MOVEMENT_VALUE("velMaxReverse", m_velMaxReverse); MOVEMENT_VALUE("acceleration", m_accel); MOVEMENT_VALUE("accelerationVelMax", m_accelVelMax); MOVEMENT_VALUE("accelerationMultiplier", m_accelCoeff); MOVEMENT_VALUE("pushTilt", m_pushTilt); MOVEMENT_VALUE("turnRateMax", m_turnRateMax); MOVEMENT_VALUE("turnAccel", m_turnAccel); MOVEMENT_VALUE("cornerForce", m_cornerForceCoeff); MOVEMENT_VALUE("cornerTilt", m_cornerTilt); MOVEMENT_VALUE("turnDamping", m_turnDamping); MOVEMENT_VALUE("turnAccelMultiplier", m_turnAccelCoeff); MOVEMENT_VALUE_OPT("rollAccel", m_rollAccel, table); MOVEMENT_VALUE_OPT("pedalLimitReverse", m_pedalLimitReverse, table); MOVEMENT_VALUE_OPT("turnVelocityMult", m_turnVelocityMult, table); MOVEMENT_VALUE_OPT("velLift", m_velLift, table); MOVEMENT_VALUE_OPT("lateralDamping", m_lateralDamping, table); table.getAttr("waveIdleStrength", m_waveIdleStrength); table.getAttr("waveSpeedMult", m_waveSpeedMult); if (table.haveAttr("cornerHelper")) { if (IVehicleHelper* pHelper = m_pVehicle->GetHelper(table.getAttr("cornerHelper"))) m_cornerOffset = pHelper->GetVehicleSpaceTranslation(); } if (table.haveAttr("pushHelper")) { if (IVehicleHelper* pHelper = m_pVehicle->GetHelper(table.getAttr("pushHelper"))) m_pushOffset = pHelper->GetVehicleSpaceTranslation(); } // compute inertia [assumes box] AABB bbox; IVehiclePart* pMassPart = pVehicle->GetPart("mass"); if (!pMassPart) pMassPart = pVehicle->GetPart("massBox"); if (pMassPart) { bbox = pMassPart->GetLocalBounds(); } else { GameWarning("[CVehicleMovementStdBoat]: initialization: No \"mass\" geometry found!"); m_pEntity->GetLocalBounds(bbox); } m_maxSpeed = m_velMax; float mass = pVehicle->GetMass(); float width = bbox.max.x - bbox.min.x; float length = bbox.max.y - bbox.min.y; float height = bbox.max.z - bbox.min.z; m_Inertia.x = mass * (sqr(length)+ sqr(height)) / 12; m_Inertia.y = mass * (sqr(width) + sqr(height)) / 12; m_Inertia.z = mass * (sqr(width) + sqr(length)) / 12; m_massOffset = bbox.GetCenter(); //CryLog("[StdBoat movement]: got mass offset (%f, %f, %f)", m_massOffset.x, m_massOffset.y, m_massOffset.z); m_pSplashPos = m_pVehicle->GetHelper("splashPos"); if (m_pSplashPos) m_lastWakePos = m_pSplashPos->GetWorldSpaceTranslation(); else m_lastWakePos = m_pVehicle->GetEntity()->GetWorldTM().GetTranslation(); const char* waveEffect = ""; MOVEMENT_VALUE_OPT("waveEffect", &waveEffect, table); m_pWaveEffect = gEnv->pParticleManager->FindEffect(waveEffect, "MovementStdBoat"); m_waveTimer = cry_random(0.0f, gf_PI); m_diving = false; m_wakeSlot = -1; m_waveSoundPitch = 0.f; m_rpmPitchDir = 0; m_waveSoundAmount = 0.1f; // AI related m_prevAngle = 0.0f; m_factorMaxSpeed = 1.f; m_factorAccel = 1.f; return true; }