//------------------------------------------------------------------------ bool CVehicleActionEntityAttachment::Init(IVehicle *pVehicle, const CVehicleParams &table) { m_pVehicle = pVehicle; CVehicleParams entityAttachmentTable = table.findChild("EntityAttachment"); if(!entityAttachmentTable) return false; if(entityAttachmentTable.haveAttr("helper")) m_pHelper = m_pVehicle->GetHelper(entityAttachmentTable.getAttr("helper")); if(entityAttachmentTable.haveAttr("class")) { IEntityClassRegistry *pClassRegistry = gEnv->pEntitySystem->GetClassRegistry(); assert(pClassRegistry); m_entityClassName = entityAttachmentTable.getAttr("class"); if(IEntityClass *pEntityClass = pClassRegistry->FindClass(m_entityClassName.c_str())) { SpawnEntity(); return true; } } return false; }
//------------------------------------------------------------------------ bool CVehicleMovementWarrior::Init(IVehicle *pVehicle, const CVehicleParams &table) { CVehicleParams hovercraftTable = table.findChild("Hovercraft"); if(!hovercraftTable) return false; if(!CVehicleMovementHovercraft::Init(pVehicle, hovercraftTable)) return false; table.getAttr("maxThrustersDamaged", m_maxThrustersDamaged); table.getAttr("collapsedFeetAngle", m_collapsedFeetAngle); table.getAttr("collapsedLegAngle", m_collapsedLegAngle); table.getAttr("recoverTime", m_recoverTime); // save original thruster values m_thrustersInit.reserve(m_vecThrusters.size()); for(TThrusters::iterator it=m_vecThrusters.begin(); it!=m_vecThrusters.end(); ++it) { m_thrustersInit.push_back(new SThruster(**it)); } m_pTurret = m_pVehicle->GetPart("turret1"); m_pCannon = m_pVehicle->GetPart("cannon"); m_pWing = m_pVehicle->GetPart("generator"); m_pPlatformPos = m_pVehicle->GetHelper("platform_pos"); return true; }
//------------------------------------------------------------------------ bool CVehicleSeatActionRotateTurret::InitRotationSounds(const CVehicleParams &rotationParams, EVehicleTurretRotationType eType) { CVehicleParams sound = rotationParams.findChild("Sound"); if (!sound) return false; if (sound.haveAttr("event")) { if (string helperName = sound.getAttr("helper")) { if (IVehicleHelper* pHelper = m_pVehicle->GetHelper(helperName)) { SVehicleSoundInfo info; info.name = sound.getAttr("event"); info.pHelper = pHelper; m_rotations[eType].m_turnSoundId = m_pVehicle->AddSoundEvent(info); if (sound.haveAttr("eventDamage")) { SVehicleSoundInfo dmgInfo; info.name = sound.getAttr("eventDamage"); info.pHelper = pHelper; m_rotations[eType].m_damageSoundId = m_pVehicle->AddSoundEvent(info); } return true; } } return false; } return true; }
//------------------------------------------------------------------------ bool CVehicleDamageBehaviorImpulse::Init(IVehicle* pVehicle, const CVehicleParams& table) { m_pVehicle = (CVehicle*) pVehicle; CVehicleParams impulseParams = table.findChild("Impulse"); if (!impulseParams) return false; impulseParams.getAttr("worldSpace", m_worldSpace); impulseParams.getAttr("forceMin", m_forceMin); impulseParams.getAttr("forceMax", m_forceMax); impulseParams.getAttr("direction", m_impulseDir); m_impulseDir.NormalizeSafe(Vec3(0,0,1)); if (!impulseParams.getAttr("momentum", m_angImpulse)) m_angImpulse.zero(); if (impulseParams.haveAttr("helper")) m_pImpulseLocation = m_pVehicle->GetHelper(impulseParams.getAttr("helper")); else m_pImpulseLocation = NULL; return true; }
//------------------------------------------------------------------------ bool CVehicleActionDeployRope::Init(IVehicle *pVehicle, IVehicleSeat *pSeat, const CVehicleParams &table) { m_pVehicle = pVehicle; m_pSeat = pSeat; CVehicleParams deployRopeTable = table.findChild("DeployRope"); if(!deployRopeTable) return false; if(deployRopeTable.haveAttr("helper")) m_pRopeHelper = m_pVehicle->GetHelper(deployRopeTable.getAttr("helper")); if(deployRopeTable.haveAttr("animation")) { if(m_pDeployAnim = m_pVehicle->GetAnimation(deployRopeTable.getAttr("animation"))) { m_deployAnimOpenedId = m_pDeployAnim->GetStateId("opened"); m_deployAnimClosedId = m_pDeployAnim->GetStateId("closed"); if(m_deployAnimOpenedId == InvalidVehicleAnimStateId || m_deployAnimClosedId == InvalidVehicleAnimStateId) { m_pDeployAnim = NULL; } } } return m_pRopeHelper != NULL; }
//------------------------------------------------------------------------ bool CVehicleMovementVTOL::Init(IVehicle *pVehicle, const CVehicleParams &table) { if (!CVehicleMovementHelicopter::Init(pVehicle, table)) { return false; } MOVEMENT_VALUE("horizFwdForce", m_horizFwdForce); MOVEMENT_VALUE("horizLeftForce", m_horizLeftForce); MOVEMENT_VALUE("boostForce", m_boostForce); MOVEMENT_VALUE("strafeForce", m_strafeForce); MOVEMENT_VALUE("angleLift", m_angleLift); m_playerDampingBase = 0.15f; m_playerDampingRotation = 0.3f; m_playerDimLowInput = 0.01f; m_playerRotationMult.x = 55.0f; m_playerRotationMult.y = 40.0f; m_playerRotationMult.z = 0.0f; m_maxFwdSpeedHorizMode = m_maxFwdSpeed; m_maxUpSpeedHorizMode = m_maxUpSpeed; m_pWingsAnimation = NULL; m_wingHorizontalStateId = InvalidVehicleAnimStateId; m_wingVerticalStateId = InvalidVehicleAnimStateId; if (!table.getAttr("timeUntilWingsRotate", m_timeUntilWingsRotate)) { m_timeUntilWingsRotate = 0.65f; } m_engineUpDir.Set(0.0f, 0.0f, 1.0f); if (!table.getAttr("wingsSpeed", m_wingsSpeed)) { m_wingsSpeed = 1.0f; } m_playerDampingBase *= 3.0f; m_fwdPID.Reset(); m_fwdPID.m_kP = 0.66f; m_fwdPID.m_kD = 0.2f; m_fwdPID.m_kI = 0.0f; m_relaxForce = 0.50f; m_relaxPitchTime = 0.0f; m_relaxRollTime = 0.0f; m_playerControls.RegisterValue(&m_forwardAction, false, 0.0f, "forward"); m_playerControls.RegisterAction(eVAI_MoveForward, CHelicopterPlayerControls::eVM_Positive, &m_forwardAction); m_playerControls.RegisterAction(eVAI_MoveBack, CHelicopterPlayerControls::eVM_Negative, &m_forwardAction); m_playerControls.RegisterValue(&m_strafeAction, false, 0.0f, "strafe"); m_playerControls.RegisterAction(eVAI_StrafeLeft, CHelicopterPlayerControls::eVM_Negative, &m_strafeAction); m_playerControls.RegisterAction(eVAI_StrafeRight, CHelicopterPlayerControls::eVM_Positive, &m_strafeAction); m_playerControls.SetActionMult(eVAI_RotateYaw, m_maxYawRate * 0.4f); m_playerControls.SetActionMult(eVAI_RotatePitch, m_maxYawRate * 0.4f); m_pStabilizeVTOL = gEnv->pConsole->GetCVar("v_stabilizeVTOL"); m_maxSpeed = 75.0f; return true; }
//------------------------------------------------------------------------ bool CVehicleDamageBehaviorEffect::Init(IVehicle *pVehicle, const CVehicleParams &table) { m_pVehicle = pVehicle; m_pDamageEffect = NULL; m_slot = -1; CVehicleParams effectParams = table.findChild("Effect"); if(!effectParams) { return false; } string effectName = effectParams.getAttr("effect"); CryFixedStringT<256> sharedParamsName; sharedParamsName.Format("%s::DamageBehaviorEffect::%s", pVehicle->GetEntity()->GetClass()->GetName(), effectName.c_str()); ISharedParamsManager *pSharedParamsManager = CCryAction::GetCryAction()->GetISharedParamsManager(); CRY_ASSERT(pSharedParamsManager); m_pSharedParams = CastSharedParamsPtr<SSharedParams>(pSharedParamsManager->Get(sharedParamsName)); if(!m_pSharedParams) { SSharedParams sharedParams; sharedParams.effectName = effectName; sharedParams.damageRatioMin = 1.0f; sharedParams.updateFromHelper = false; table.getAttr("damageRatioMin", sharedParams.damageRatioMin); sharedParams.disableAfterExplosion = false; effectParams.getAttr("disableAfterExplosion", sharedParams.disableAfterExplosion); effectParams.getAttr("updateFromHelper", sharedParams.updateFromHelper); m_pSharedParams = CastSharedParamsPtr<SSharedParams>(pSharedParamsManager->Register(sharedParamsName, sharedParams)); } CRY_ASSERT(m_pSharedParams.get()); return true; }
//------------------------------------------------------------------------ bool CVehicleUsableActionEnter::Init(IVehicle* pVehicle, const CVehicleParams& table) { CVehicleParams enterTable = table.findChild("Enter"); if (!enterTable) return false; m_pVehicle = static_cast<CVehicle*>(pVehicle); if (CVehicleParams seatsTables = enterTable.findChild("Seats")) { int c = seatsTables.getChildCount(); int i = 0; m_seatIds.reserve(c); for (; i < c; i++) { CVehicleParams seatRef = seatsTables.getChild(i); if (const char* pSeatName = seatRef.getAttr("value")) { if (TVehicleSeatId seatId = m_pVehicle->GetSeatId(pSeatName)) m_seatIds.push_back(seatId); } } } return !m_seatIds.empty(); }
//------------------------------------------------------------------------ bool CVehicleDamageBehaviorBurn::Init(IVehicle *pVehicle, const CVehicleParams &table) { m_pVehicle = pVehicle; m_isActive = false; m_damageRatioMin = 1.f; m_timerId = -1; m_shooterId = 0; table.getAttr("damageRatioMin", m_damageRatioMin); if(CVehicleParams burnTable = table.findChild("Burn")) { burnTable.getAttr("damage", m_damage); burnTable.getAttr("selfDamage", m_selfDamage); burnTable.getAttr("interval", m_interval); burnTable.getAttr("radius", m_radius); m_pHelper = NULL; if(burnTable.haveAttr("helper")) m_pHelper = m_pVehicle->GetHelper(burnTable.getAttr("helper")); else m_pHelper = NULL; return true; } return false; }
void CVehicleMovementHelicopter::InitMovementNoise( const CVehicleParams& noiseParams, CVTolNoise& noise ) { Vec3 amplitude(ZERO); Vec3 frequency(ZERO); Vec3 rotAmplitudeDeg(ZERO); Vec3 rotFrequency(ZERO); float startDamageRatio = 0.f; noiseParams.getAttr("amplitude", amplitude); noiseParams.getAttr("frequency", frequency); noiseParams.getAttr("rotAmplitude", rotAmplitudeDeg); noiseParams.getAttr("rotFrequency", rotFrequency); noiseParams.getAttr("startDamageRatio", startDamageRatio); noise.Init(amplitude, frequency, DEG2RAD(rotAmplitudeDeg), rotFrequency, startDamageRatio); }
//------------------------------------------------------------------------ bool CVehicleSeatGroup::Init(IVehicle* pVehicle, const CVehicleParams& paramsTable) { m_pVehicle = static_cast<CVehicle*>(pVehicle); m_isSwitchingReverse = false; if (CVehicleParams seatsTable = paramsTable.findChild("Seats")) { int i = 0; int c = seatsTable.getChildCount(); m_seats.reserve(c); for (; i < c; i++) { string seatName = seatsTable.getChild(i).getAttr("value"); if (!seatName.empty()) { TVehicleSeatId seatId = m_pVehicle->GetSeatId(seatName); if (CVehicleSeat* pSeat = (CVehicleSeat*)m_pVehicle->GetSeatById(seatId)) { pSeat->SetSeatGroup(this); m_seats.push_back(pSeat); } } } } if (!paramsTable.getAttr("keepEngineWarm", m_isKeepingEngineWarm)) m_isKeepingEngineWarm = false; return !m_seats.empty(); }
//------------------------------------------------------------------------ bool CVehicleDamagesGroup::Init(CVehicle* pVehicle, const CVehicleParams& table) { m_pVehicle = pVehicle; m_name = table.getAttr("name"); m_damageSubGroups.clear(); return !m_name.empty() && ParseDamagesGroup(table); }
//------------------------------------------------------------------------ bool CVehicleMovementHelicopter::Init(IVehicle* pVehicle, const CVehicleParams& table) { if (!CVehicleMovementBase::Init(pVehicle, table)) return false; // Initialise the arcade physics, handling helper if (CVehicleParams handlingParams = table.findChild("HandlingArcade")) if (!m_arcade.Init(pVehicle, handlingParams)) return false; MOVEMENT_VALUE("engineWarmupDelay", m_engineWarmupDelay); MOVEMENT_VALUE("enginePowerMax", m_enginePowerMax); MOVEMENT_VALUE("yawPerRoll", m_yawPerRoll); MOVEMENT_VALUE("maxSpeed", m_maxSpeed); MOVEMENT_VALUE("maxPitchAngle", m_maxPitchAngle); MOVEMENT_VALUE("maxRollAngle", m_maxRollAngle); MOVEMENT_VALUE("rollDamping", m_rollDamping); if(table.haveAttr("extendMoveTarget")) { table.getAttr("extendMoveTarget", m_bExtendMoveTarget); } table.getAttr("applyNoiseAsVelocity", m_bApplyNoiseAsVelocity); if(CVehicleParams noiseParams = table.findChild("MovementNoise")) { InitMovementNoise(noiseParams, m_defaultNoise); } // high-level controller Ang3 angles = m_pEntity->GetWorldAngles(); m_enginePower = 0.0f; if (table.haveAttr("rotorPartName")) m_pRotorPart = m_pVehicle->GetPart(table.getAttr("rotorPartName")); m_isEngineGoingOff = true; m_isEnginePowered = false; ResetActions(); m_pVehicle->GetGameObject()->EnableUpdateSlot(m_pVehicle, IVehicle::eVUS_EnginePowered); return true; }
static void getFlag(CVehicleParams ¶ms, const char* key, int &flags, int flag) { int tmp = flags & flag; params.getAttr(key, tmp); if (tmp) flags |= flag; else flags &= ~flag; }
//------------------------------------------------------------------------ bool CVehicleSeatActionRotateTurret::InitRotation(IVehicle* pVehicle, const CVehicleParams &rotationTable, EVehicleTurretRotationType eType) { if (rotationTable) { if (rotationTable.haveAttr("part")) m_rotations[eType].m_pPart = static_cast<CVehiclePartBase*>(m_pVehicle->GetPart(rotationTable.getAttr("part"))); if (rotationTable.getAttr("speed", m_rotations[eType].m_speed) && m_rotations[eType].m_pPart) { m_rotations[eType].m_pPart->SetMoveable(); rotationTable.getAttr("accel", m_rotations[eType].m_acceleration); if (CVehicleParams limitsTable = rotationTable.findChild("Limits")) { // Forward facing limits if (limitsTable.getChildCount() >= 2) { if (CVehicleParams limitRef = limitsTable.getChild(0)) m_rotations[eType].m_minLimitF = (float)DEG2RAD((float)atof(limitRef.getAttr("value"))); else m_rotations[eType].m_minLimitF = 0.0f; if (CVehicleParams limitRef = limitsTable.getChild(1)) m_rotations[eType].m_maxLimit = (float)DEG2RAD((float)atof(limitRef.getAttr("value"))); else m_rotations[eType].m_maxLimit = 0.0f; } // Backwards facing limits m_rotations[eType].m_minLimitB = m_rotations[eType].m_minLimitF; if (limitsTable.getChildCount() >= 3) { if (CVehicleParams limitRef = limitsTable.getChild(2)) m_rotations[eType].m_minLimitB = (float)DEG2RAD((float)atof(limitRef.getAttr("value"))); } } } rotationTable.getAttr("worldSpace", m_rotations[eType].m_worldSpace); } return true; }
bool CVehicleSeatActionOrientateBoneToView::Init(IVehicle* pVehicle, IVehicleSeat* pSeat, const CVehicleParams& table) { m_pVehicle = pVehicle; m_pSeat = pSeat; IDefaultSkeleton& rIDefaultSkeleton = *GetCharacterModelSkeleton(); { if(table.haveAttr("MoveBone") ) { const char* boneName = table.getAttr("MoveBone"); m_MoveBoneId = rIDefaultSkeleton.GetJointIDByName(boneName); } if(table.haveAttr("LookBone") ) { const char* boneName = table.getAttr("LookBone"); m_LookBoneId = rIDefaultSkeleton.GetJointIDByName(boneName); } } if( table.haveAttr("Sluggishness") ) { table.getAttr("Sluggishness", m_Sluggishness); } if ( CVehicleParams baseOrientationTable = table.findChild("MoveBoneBaseOrientation") ) { float x, y, z; baseOrientationTable.getAttr("x", x); baseOrientationTable.getAttr("y", y); baseOrientationTable.getAttr("z", z); m_BoneBaseOrientation = Quat::CreateRotationXYZ( Ang3(x, y, z) ); } else { m_BoneBaseOrientation.SetIdentity(); } return true; }
//------------------------------------------------------------------------ bool CVehicleSeatActionSound::Init(IVehicle* pVehicle, IVehicleSeat* pSeat, const CVehicleParams& table) { m_pVehicle = pVehicle; m_pSeat = static_cast<CVehicleSeat*>(pSeat); CVehicleParams soundTable = table.findChild("Audio"); if (!soundTable) return false; gEnv->pAudioSystem->GetAudioTriggerID(soundTable.getAttr("startTrigger"), m_nAudioControlIDStart); gEnv->pAudioSystem->GetAudioTriggerID(soundTable.getAttr("stopTrigger"), m_nAudioControlIDStop); if (soundTable.haveAttr("helper")) m_pHelper = m_pVehicle->GetHelper(soundTable.getAttr("helper")); if (!m_pHelper) return false; m_enabled = false; return true; }
//------------------------------------------------------------------------ bool CVehicleDamageBehaviorExplosion::Init(IVehicle* pVehicle, const CVehicleParams& table) { m_pVehicle = pVehicle; m_exploded = false; CVehicleParams explosionParams = table.findChild("Explosion"); if (!explosionParams) return false; explosionParams.getAttr("damage", m_damage); explosionParams.getAttr("radius", m_radius); explosionParams.getAttr("pressure", m_pressure); if (!explosionParams.getAttr("minRadius", m_minRadius)) m_minRadius = m_radius/2.0f; if (!explosionParams.getAttr("physRadius", m_physRadius)) m_physRadius = min(m_radius, 5.0f); if (!explosionParams.getAttr("minPhysRadius", m_minPhysRadius)) m_minPhysRadius = m_physRadius/2.0f; if (explosionParams.haveAttr("helper")) m_pHelper = m_pVehicle->GetHelper(explosionParams.getAttr("helper")); else m_pHelper = NULL; return true; }
//------------------------------------------------------------------------ bool CVehicleActionAutomaticDoor::Init(IVehicle* pVehicle, const CVehicleParams& table) { m_pVehicle = pVehicle; CVehicleParams autoDoorTable = table.findChild("AutomaticDoor"); if (!autoDoorTable) return false; if (autoDoorTable.haveAttr("animation")) m_pDoorAnim = m_pVehicle->GetAnimation(autoDoorTable.getAttr("animation")); autoDoorTable.getAttr("timeMax", m_timeMax); if (!m_pDoorAnim) return false; m_doorOpenedStateId = m_pDoorAnim->GetStateId("opened"); m_doorClosedStateId = m_pDoorAnim->GetStateId("closed"); autoDoorTable.getAttr("disabled", m_isDisabled); m_pVehicle->SetObjectUpdate(this, IVehicle::eVOU_AlwaysUpdate); m_pVehicle->RegisterVehicleEventListener(this, "VehicleActionAutomaticDoor"); m_pDoorAnim->StopAnimation(); m_pDoorAnim->StartAnimation(); m_pDoorAnim->ToggleManualUpdate(true); if(!m_isDisabled) m_pDoorAnim->SetTime(DOOR_OPENED); else { m_pDoorAnim->SetTime(DOOR_CLOSED); m_animTime = DOOR_CLOSED; m_animGoal = DOOR_CLOSED; } return true; }
bool CVehiclePartWaterRipplesGenerator::Init(IVehicle* pVehicle, const CVehicleParams& table, IVehiclePart* parent, CVehicle::SPartInitInfo& initInfo, int partType) { if (!CVehiclePartBase::Init(pVehicle, table, parent, initInfo, eVPT_Massbox)) return false; m_pVehicle = pVehicle; const CVehicleParams waterRipplesTable = table.findChild("WaterRipplesGen"); if (waterRipplesTable) { waterRipplesTable.getAttr("scale", m_waterRipplesScale); waterRipplesTable.getAttr("strength", m_waterRipplesStrength); waterRipplesTable.getAttr("minMovementSpeed", m_minMovementSpeed); waterRipplesTable.getAttr("moveForwardOnly", m_onlyMovingForward); m_minMovementSpeed = max( m_minMovementSpeed, 0.01f ); } m_pVehicle->SetObjectUpdate(this, IVehicle::eVOU_AlwaysUpdate); return true; }
//------------------------------------------------------------------------ bool CVehicleSeatActionAnimation::Init(IVehicle* pVehicle, IVehicleSeat* pSeat, const CVehicleParams &table) { m_pVehicle = pVehicle; CVehicleParams animTable = table.findChild("Animation"); if (!animTable) return false; if (animTable.haveAttr("vehicleAnimation")) m_pVehicleAnim = m_pVehicle->GetAnimation(animTable.getAttr("vehicleAnimation")); string control = animTable.getAttr("control"); if (!control.empty()) { if (control == "roll") { m_control[0] = eVAI_RollLeft; m_control[1] = eVAI_RollRight; } } animTable.getAttr("manualUpdate", m_manualUpdate); animTable.getAttr("speed", m_speed); REINST("start/stop event?"); /*m_pIEntityAudioProxy = (IEntityAudioProxy*)m_pVehicle->GetEntity()->GetProxy(ENTITY_PROXY_AUDIO); if (m_pIEntityAudioProxy) { if (animTable.haveAttr("sound")) m_pSound = gEnv->pAudioSystem->CreateSound(animTable.getAttr("sound"), FLAG_SOUND_DEFAULT_3D); if (animTable.haveAttr("stopSound")) m_pStopSound = gEnv->pAudioSystem->CreateSound(animTable.getAttr("stopSound"), FLAG_SOUND_DEFAULT_3D); }*/ return true; }
//------------------------------------------------------------------------ bool CVehicleSeatActionPassengerIK::Init(IVehicle* pVehicle, IVehicleSeat* pSeat, const CVehicleParams& table) { m_pVehicle = pVehicle; m_passengerId = 0; CVehicleParams ikTable = table.findChild("PassengerIK"); if (!ikTable) return false; CVehicleParams limbsTable = ikTable.findChild("Limbs"); if (!limbsTable) return false; if (!ikTable.getAttr("waitShortlyBeforeStarting", m_waitShortlyBeforeStarting)) m_waitShortlyBeforeStarting = false; int i = 0; int c = limbsTable.getChildCount(); m_ikLimbs.reserve(c); for (; i < c; i++) { if (CVehicleParams limbTable = limbsTable.getChild(i)) { SIKLimb limb; if (limbTable.haveAttr("limb")) { limb.limbName = limbTable.getAttr("limb"); if (limbTable.haveAttr("helper")) { if (limb.pHelper = m_pVehicle->GetHelper(limbTable.getAttr("helper"))) m_ikLimbs.push_back(limb); } } } } return !m_ikLimbs.empty(); }
bool CVehiclePartSuspensionPart::Init(IVehicle *pVehicle, const CVehicleParams &table, IVehiclePart *pParent, CVehicle::SPartInitInfo &initInfo, int partType) { if (!inherited::Init(pVehicle, table, pParent, initInfo, partType)) return false; m_animatedRoot = CAST_VEHICLEOBJECT(CVehiclePartAnimated, GetParent(true)); m_jointId = -1; m_ikFlags = 0; if (m_animatedRoot) { if(CVehicleParams subPartTable = table.findChild("SubPart")) { // We need to remove this part from the animated root, otherwise we have two parts // NB: for now we are not doing anything with the physics - infact its preferable // if we dont have physics on suspension arms! const char* geoName = subPartTable.getAttr("geometryname"); ICharacterInstance* pCharInstance = m_animatedRoot->GetEntity()->GetCharacter(m_animatedRoot->GetSlot()); if (pCharInstance) { IDefaultSkeleton& rIDefaultSkeleton = pCharInstance->GetIDefaultSkeleton(); ISkeletonPose* pSkeletonPose = pCharInstance->GetISkeletonPose(); m_jointId = rIDefaultSkeleton.GetJointIDByName(geoName); pSkeletonPose->SetStatObjOnJoint(m_jointId, NULL); } } } else { CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "CVehiclePartSuspensionPart: needs to have an AnimatedPart as a parent!"); return false; } CVehicleParams ikTable = table.findChild("IK"); if (!ikTable) return false; const char* targetPartName = ikTable.getAttr("target"); m_targetPart = static_cast<CVehiclePartBase*>(pVehicle->GetPart(targetPartName)); if (m_targetPart==NULL) { CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "CVehiclePartSuspensionPart: couldn't find target part: '%s'", targetPartName); return false; } // Set up the target m_targetOffset.zero(); const char* targetHelper = ikTable.getAttr("targetHelper"); if (targetHelper && targetHelper[0]) { if (IVehicleHelper* pHelper = m_pVehicle->GetHelper(targetHelper)) { // NB: this is in vehicle space, and needs translating in PostInit() m_targetOffset = pHelper->GetLocalTM().GetTranslation(); m_ikFlags |= k_flagTargetHelper; } } Vec3 offset(0); ikTable.getAttr("offset", offset); m_targetOffset += offset; m_mode = k_modeStretch; const char* mode = ikTable.getAttr("mode"); if (strcmp(mode,"rotate")==0) m_mode = k_modeRotate; if (strcmp(mode,"stretch")==0) m_mode = k_modeStretch; if (strcmp(mode,"snap")==0) m_mode = k_modeSnapToEF; bool bIgnoreTargetRotation=0; ikTable.getAttr("ignoreTargetRotation", bIgnoreTargetRotation); if (bIgnoreTargetRotation) m_ikFlags |= k_flagIgnoreTargetRotation; return true; }
bool CVehicleMovementMPVTOL::Init(IVehicle* pVehicle, const CVehicleParams& table) { bool success = BaseClass::Init(pVehicle, table); //ToDo: Any VTOL animations/effects setup MOVEMENT_VALUE("rollSpeedMultiplier", m_rollSpeedMultiplier); // Control what needs to be network synced int vtolmanagerControlled = 0; table.getAttr("vtolmanagerControlled", vtolmanagerControlled); if (vtolmanagerControlled && g_pGame->GetGameRules()->GetVTOLVehicleManager()) { // No need to do low level physics synchronisation m_pVehicle->GetGameObject()->DontSyncPhysics(); // Disable some of the additional network serialisation // Disable all pos, rot serialization. All Network syncing is done via catchup along the path, handled by the manager. // The only data sent is the pathId, and the distance along the path (pathLoc) //m_netActionSync.m_actionRep.SetFlags(CNetworkMovementHelicopterCrysis2::k_syncPos|CNetworkMovementHelicopterCrysis2::k_controlPos); m_sendTime = g_pGameCVars->v_MPVTOLNetworkSyncFreq; m_updateAspects |= k_vtolPathUpdate; } if(CVehicleParams stutterParams = table.findChild("EngineStuttering")) { stutterParams.getAttr("stutterStartDamageRatio", m_stutterStartDamageRatio); if(m_stutterStartDamageRatio == 1.f) { GameWarning("CVehicleMovementMPVTOL::Init: stutterStartDamageRatio XML param == 1.0f. Will cause divide by 0 error in release."); m_stutterStartDamageRatio = 0.f; } m_invStutterDamageSpread = __fres(1.f - m_stutterStartDamageRatio); stutterParams.getAttr("minStutters", m_baseStutters); stutterParams.getAttr("maxStutters", m_maxExtraStutters); m_maxExtraStutters -= m_baseStutters; stutterParams.getAttr("minTimeBetweenStutters", m_minTimeBetweenStutters); stutterParams.getAttr("maxTimeBetweenStutters", m_maxTimeBetweenStutters); stutterParams.getAttr("timeBetweenStutterDecayMult", m_timeBetweenStutterDecayMult); stutterParams.getAttr("stutterDurationOn", m_stutterDurationOn); stutterParams.getAttr("stutterDurationOff", m_stutterDurationOff); } if(CVehicleParams wingRotationParams = table.findChild("WingRotation")) { float maxAngleDeg; if(wingRotationParams.getAttr("maxAngleDeg", maxAngleDeg)) { m_maxAngleRad = DEG2RAD(maxAngleDeg); } wingRotationParams.getAttr("canReachMaxAngleAtSpeed", m_maxAngleSpeed); CRY_ASSERT_MESSAGE(m_maxAngleSpeed, "CVehicleMovementMPVTOL::Init - canReachMaxAngleAtSpeed is 0. This will result in divide by 0 error during update."); wingRotationParams.getAttr("angleAngularVelMult", m_angularVelMult); wingRotationParams.getAttr("smoothTime", m_angleSmoothTime); wingRotationParams.getAttr("insideWingSpeedMult", m_insideWingSpeedMult); wingRotationParams.getAttr("insideWingMaxAngleMult", m_insideWingMaxAngleMult); float noiseAmp = 0.f; float noiseFreq = 0.f; wingRotationParams.getAttr("noiseAmplitude", noiseAmp); wingRotationParams.getAttr("noiseFrequency", noiseFreq); m_leftWingNoise.Setup(noiseAmp, noiseFreq, 0x473845); m_rightWingNoise.Setup(noiseAmp, noiseFreq, 0x287463); } if(CVehicleParams noiseOverrideParams = table.findChild("NoiseOverrides")) { int count = noiseOverrideParams.getChildCount(); for(int i = 0; i < count; ++i) { if(i == MAX_NOISE_OVERRIDES) { GameWarning("CVehicleMovementMPVTOL::Init - %i noise overrides specified in XML but only %i currently supported. Needs code change to support more.", count, MAX_NOISE_OVERRIDES); break; } InitMovementNoise(noiseOverrideParams.getChild(i), m_noiseOverrides[i]); } } pVehicle->RegisterVehicleEventListener(this, "CVehicleMovementMPVTOL"); return success; }
//------------------------------------------------------------------------ bool CVehicleDamagesGroup::ParseDamagesGroup(const CVehicleParams& table) { if (table.haveAttr("useTemplate")) { IVehicleSystem* pVehicleSystem = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem(); CRY_ASSERT(pVehicleSystem); if (IVehicleDamagesTemplateRegistry* pDamageTemplReg = pVehicleSystem->GetDamagesTemplateRegistry()) pDamageTemplReg->UseTemplate(table.getAttr("useTemplate"), this); } if (CVehicleParams damagesSubGroupsTable = table.findChild("DamagesSubGroups")) { int i = 0; int c = damagesSubGroupsTable.getChildCount(); for (; i < c; i++) { if (CVehicleParams groupTable = damagesSubGroupsTable.getChild(i)) { m_damageSubGroups.resize(m_damageSubGroups.size() + 1); SDamagesSubGroup& subGroup = m_damageSubGroups.back(); subGroup.id = m_damageSubGroups.size() - 1; subGroup.m_isAlreadyInProcess = false; if (!groupTable.getAttr("delay", subGroup.m_delay)) subGroup.m_delay = 0.0f; if (!groupTable.getAttr("randomness", subGroup.m_randomness)) subGroup.m_randomness = 0.0f; if (CVehicleParams damageBehaviorsTable = groupTable.findChild("DamageBehaviors")) { int k = 0; int numDamageBehaviors = damageBehaviorsTable.getChildCount(); subGroup.m_damageBehaviors.reserve(c); for (; k < numDamageBehaviors; k++) { if (CVehicleParams behaviorTable = damageBehaviorsTable.getChild(k)) { if (IVehicleDamageBehavior* pDamageBehavior = ParseDamageBehavior(behaviorTable)) { subGroup.m_damageBehaviors.push_back(pDamageBehavior); CVehicleDamageBehaviorDestroy *pDamageDestroy = CAST_VEHICLEOBJECT(CVehicleDamageBehaviorDestroy, pDamageBehavior); if (pDamageDestroy) { TVehiclePartVector& parts = m_pVehicle->GetParts(); for (TVehiclePartVector::iterator ite = parts.begin(); ite != parts.end(); ++ite) { IVehiclePart* pPart = ite->second; if (CVehiclePartAnimatedJoint* pAnimJoint = CAST_VEHICLEOBJECT(CVehiclePartAnimatedJoint, pPart)) { if (pAnimJoint->IsPhysicalized() && !pAnimJoint->GetDetachBaseForce().IsZero()) { CVehicleDamageBehaviorDetachPart* pDetachBehavior = new CVehicleDamageBehaviorDetachPart; pDetachBehavior->Init(m_pVehicle, pAnimJoint->GetName(), pDamageDestroy->GetEffectName()); subGroup.m_damageBehaviors.push_back(pDetachBehavior); } } } } } } } } } } } return true; }
//------------------------------------------------------------------------ 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; }
//------------------------------------------------------------------------ bool CVehicleMovementHelicopter::Init(IVehicle *pVehicle, const CVehicleParams &table) { if(!CVehicleMovementBase::Init(pVehicle, table)) assert(0); MOVEMENT_VALUE("engineWarmupDelay", m_engineWarmupDelay); // heli abilities MOVEMENT_VALUE("altitudeMax", m_altitudeMax); MOVEMENT_VALUE("rotorDiskTiltScale", m_rotorDiskTiltScale); MOVEMENT_VALUE("pitchResponsiveness", m_pitchResponsiveness); MOVEMENT_VALUE("rollResponsiveness", m_rollResponsiveness); MOVEMENT_VALUE("yawResponsiveness", m_yawResponsiveness); MOVEMENT_VALUE("enginePowerMax", m_enginePowerMax); MOVEMENT_VALUE("rotationDamping", m_rotationDamping); MOVEMENT_VALUE("yawPerRoll", m_yawPerRoll); // high-level controller abilities MOVEMENT_VALUE("maxYawRate", m_maxYawRate); MOVEMENT_VALUE("maxFwdSpeed", m_maxFwdSpeed); MOVEMENT_VALUE("maxLeftSpeed", m_maxLeftSpeed); MOVEMENT_VALUE("maxUpSpeed", m_maxUpSpeed); MOVEMENT_VALUE("basicSpeedFraction", m_basicSpeedFraction); MOVEMENT_VALUE("yawDecreaseWithSpeed", m_yawDecreaseWithSpeed); MOVEMENT_VALUE("tiltPerVelDifference", m_tiltPerVelDifference); MOVEMENT_VALUE("maxTiltAngle", m_maxTiltAngle); MOVEMENT_VALUE("extraRollForTurn", m_extraRollForTurn); MOVEMENT_VALUE("rollForTurnForce", m_rollForTurnForce); MOVEMENT_VALUE("yawPerRoll", m_yawPerRoll); MOVEMENT_VALUE("pitchActionPerTilt", m_pitchActionPerTilt); MOVEMENT_VALUE("pitchInputConst", m_pitchInputConst); MOVEMENT_VALUE("powerInputConst", m_powerInputConst); MOVEMENT_VALUE("powerInputDamping", m_powerInputDamping); MOVEMENT_VALUE("relaxForce", m_relaxForce); MOVEMENT_VALUE("yawInputConst", m_yawInputConst); MOVEMENT_VALUE("yawInputDamping", m_yawInputDamping); MOVEMENT_VALUE("maxRollAngle", m_maxRollAngle); MOVEMENT_VALUE("velDamping", m_velDamp); // Initialise the power PID. m_powerPID.Reset(); m_powerPID.m_kP = 0.2f; m_powerPID.m_kD = 0.01f; m_powerPID.m_kI = 0.0001f; m_maxSpeed = 40.f; // empirically determined m_liftPID.Reset(); m_yawPID.Reset(); m_liftPID.m_kP = 0.66f; m_liftPID.m_kD = 0.2f; m_liftPID.m_kI = 0.0f; m_yawPID.m_kP = -0.03f; m_yawPID.m_kI = 0.0f; m_yawPID.m_kD = 0.0f; // high-level controller Ang3 angles = m_pEntity->GetWorldAngles(); m_desiredDir = angles.z; m_desiredHeight = m_pEntity->GetWorldPos().z; m_lastDir = m_desiredDir; m_enginePower = 0.0f; m_isTouchingGround = false; m_timeOnTheGround = 50.0f; if(table.haveAttr("rotorPartName")) m_pRotorPart = m_pVehicle->GetPart(table.getAttr("rotorPartName")); else m_pRotorPart = NULL; m_desiredPitch = 0.0f; ResetActions(); m_playerDampingBase = 0.1f; m_playerDampingRotation = 0.15f; m_playerDimLowInput = 0.25f; m_playerRotationMult.x = 60.0f; m_playerRotationMult.y = 60.0f; m_playerRotationMult.z = 10.0f; m_strafeForce = 1.0f; m_engineUpDir.Set(0.0f, 0.0f, 1.0f); m_boostMult = 2.00f; ICVar *pSensitivVar = gEnv->pConsole->GetCVar("cl_sensitivity"); m_playerControls.RegisterValue(&m_liftAction, false, 0.0f, "lift"); m_playerControls.RegisterAction(eVAI_MoveUp, CHelicopterPlayerControls::eVM_Positive, &m_liftAction); m_playerControls.RegisterAction(eVAI_MoveDown, CHelicopterPlayerControls::eVM_Negative, &m_liftAction); m_playerControls.RegisterValue(&m_turnAction, false, 0.0f, "roll"); m_playerControls.RegisterAction(eVAI_TurnLeft, CHelicopterPlayerControls::eVM_Negative, &m_turnAction); m_playerControls.RegisterAction(eVAI_TurnRight, CHelicopterPlayerControls::eVM_Positive, &m_turnAction); m_playerControls.RegisterAction(eVAI_RotateYaw, CHelicopterPlayerControls::eVM_Positive, &m_turnAction, pSensitivVar); m_playerControls.SetActionMult(eVAI_RotateYaw, m_maxYawRate * 0.65f); m_playerControls.RegisterValue(&m_desiredRoll, false, gf_PI * 4.0f, "turn"); m_playerControls.RegisterAction(eVAI_RollLeft, CHelicopterPlayerControls::eVM_Negative, &m_desiredRoll); m_playerControls.RegisterAction(eVAI_RollRight, CHelicopterPlayerControls::eVM_Positive, &m_desiredRoll); m_playerControls.RegisterAction(eVAI_RotateRoll, CHelicopterPlayerControls::eVM_Positive, &m_desiredRoll, pSensitivVar); m_playerControls.RegisterValue(&m_desiredPitch, false, 0.0f, "pitch"); m_playerControls.RegisterAction(eVAI_RotatePitch, CHelicopterPlayerControls::eVM_Negative, &m_desiredPitch, pSensitivVar); m_playerControls.SetActionMult(eVAI_RotatePitch, m_maxYawRate * 0.65f); m_pInvertPitchVar = gEnv->pConsole->GetCVar("v_invertPitchControl"); m_pAltitudeLimitVar = gEnv->pConsole->GetCVar("v_altitudeLimit"); m_pAltitudeLimitLowerOffsetVar = gEnv->pConsole->GetCVar("v_altitudeLimitLowerOffset"); m_pStabilizeVTOL = gEnv->pConsole->GetCVar("v_stabilizeVTOL"); m_turbulenceMultMax = 0.25f; return true; }
//------------------------------------------------------------------------ bool CVehicleViewSteer::Init(IVehicleSeat* pSeat, const CVehicleParams &table) { if (!CVehicleViewBase::Init(pSeat, table)) return false; m_pAimPart = pSeat->GetAimPart(); CVehicleParams params = table.findChild(m_name); if (!params) return false; CVehicleParams posParams = params.findChild("Pos"); CVehicleParams rotationParams = params.findChild("Rotation"); CVehicleParams motionParams = params.findChild("Motion"); CVehicleParams backwardsParams = params.findChild("Backwards"); CVehicleParams radiusParams = params.findChild("Radius"); if (posParams) { posParams.getAttr("offset", m_localSpaceCameraOffset); posParams.getAttr("aim", m_lookAt0); posParams.getAttr("pivotOffset", m_pivotOffset); } if (rotationParams) { rotationParams.getAttr("rotationMax", m_maxRotation); if (rotationParams.haveAttr("rotationMax2")) { rotationParams.getAttr("rotationMax2", m_maxRotation2); } else { m_maxRotation2 = m_maxRotation / 3.0f; } m_maxRotation = DEG2RAD(m_maxRotation); m_maxRotation2 = DEG2RAD(m_maxRotation2); rotationParams.getAttr("stickSensitivity", m_stickSensitivity); rotationParams.getAttr("stickSensitivity2", m_stickSensitivity2); rotationParams.getAttr("inheritedElev", m_inheritedElev); getFlag(rotationParams, "canRotate", m_flags, eVCam_canRotate); m_inheritedElev = clamp_tpl(m_inheritedElev, 0.f, 1.f); } if (motionParams) { motionParams.getAttr("returnSpeed", m_angReturnSpeed1); motionParams.getAttr("returnSpeed2", m_angReturnSpeed2); motionParams.getAttr("angFollow", m_angSpeedCorrection0); } if (backwardsParams) { getFlag(backwardsParams, "clamp", m_backwardsFlags, eVCam_rotationClamp); getFlag(backwardsParams, "returnSpring", m_backwardsFlags, eVCam_rotationSpring); } if (radiusParams) { radiusParams.getAttr("min", m_radiusMin); radiusParams.getAttr("max", m_radiusMax); radiusParams.getAttr("relaxRate", m_radiusRelaxRate); radiusParams.getAttr("dampRate", m_radiusDampRate); radiusParams.getAttr("velInfluence", m_radiusVelInfluence); } Reset(); return true; }
//------------------------------------------------------------------------ bool CVehiclePartTread::Init(IVehicle* pVehicle, const CVehicleParams& table, IVehiclePart* parent, CVehicle::SPartInitInfo& initInfo, int partType) { if (!CVehiclePartBase::Init(pVehicle, table, parent, initInfo, eVPT_Tread)) return false; CVehicleParams subTable = table.findChild("Tread"); // Tread subtable if (!subTable) return false; string filename = subTable.getAttr("filename"); if (filename.empty()) return false; subTable.getAttr("uvSpeedMultiplier", m_uvSpeedMultiplier); if (table.haveAttr("component")) { if (CVehicleComponent* pComponent = static_cast<CVehicleComponent*>(m_pVehicle->GetComponent(table.getAttr("component")))) pComponent->AddPart(this); } m_slot = GetEntity()->LoadCharacter(m_slot, filename); m_pCharInstance = GetEntity()->GetCharacter(m_slot); if (!m_pCharInstance) return false; if (subTable.haveAttr("materialName")) { string materialName = subTable.getAttr("materialName"); materialName.MakeLower(); IMaterial* pMaterial = 0; const char* subMtlName = 0; int subMtlSlot = -1; // find tread material IEntityRenderProxy *pRenderProxy = (IEntityRenderProxy*)GetEntity()->GetProxy(ENTITY_PROXY_RENDER); if (pRenderProxy) { pMaterial = pRenderProxy->GetRenderMaterial(m_slot); if (pMaterial) { // if matname doesn't fit, look in submaterials if (string(pMaterial->GetName()).MakeLower().find(materialName) == string::npos) { for (int i=0; i < pMaterial->GetSubMtlCount(); ++i) { if (string(pMaterial->GetSubMtl(i)->GetName()).MakeLower().find(materialName) != string::npos) { subMtlName = pMaterial->GetSubMtl(i)->GetName(); subMtlSlot = i; break; } } } } } if (pMaterial) { // clone IMaterial *pCloned = pMaterial->GetMaterialManager()->CloneMultiMaterial(pMaterial, subMtlName); if (pCloned) { pRenderProxy->SetSlotMaterial(m_slot, pCloned); pMaterial = pCloned; m_pMaterial = pMaterial; } if (subMtlSlot > -1) m_pShaderResources = pMaterial->GetShaderItem(subMtlSlot).m_pShaderResources; else m_pShaderResources = pMaterial->GetShaderItem().m_pShaderResources; } if (m_pShaderResources) { for (int i = 0; i < EFTT_MAX; ++i) { if (!m_pShaderResources->GetTexture(i)) continue; SEfTexModificator& modif = *m_pShaderResources->GetTexture(i)->AddModificator(); modif.SetMember("m_eMoveType[0]", 1.0f); // ETMM_Fixed: u = m_OscRate[0] + sourceU modif.SetMember("m_OscRate[0]", 0.0f); } } } char wheelName[256]; IDefaultSkeleton& rIDefaultSkeleton = m_pCharInstance->GetIDefaultSkeleton(); for (int i=0; i<rIDefaultSkeleton.GetJointCount(); ++i) { const char* boneName = rIDefaultSkeleton.GetJointNameByID(i); if (0 != boneName) { // extract wheel name const size_t len = strcspn(boneName, "_"); if (len < strlen(boneName) && len < sizeof(wheelName)) { cry_strcpy(wheelName, boneName, len); CVehiclePartSubPartWheel* pWheel = (CVehiclePartSubPartWheel*)m_pVehicle->GetPart(wheelName); if (pWheel) { SWheelInfo wheelInfo; wheelInfo.slot = pWheel->m_slot; wheelInfo.jointId = i; wheelInfo.pWheel = pWheel; m_wheels.push_back(wheelInfo); m_lastWheelIndex = pWheel->GetWheelIndex(); } } } } m_pVehicle->SetObjectUpdate(this, IVehicle::eVOU_AlwaysUpdate); m_state = eVGS_Default; return true; }