Ejemplo n.º 1
0
bool STransition::ReadStanceParam( const char* name, bool required, const struct IItemParamsNode*const pParams, EStance*const pStance ) const
{
	const char* szStance = pParams->GetAttribute(name);

	if (!szStance && !required)
		return false;

	CRY_ASSERT_TRACE(szStance, ("%s not found", name));
	if (!szStance)
		return false;

	// look for stance name (case insensitive)
	int stance = STANCE_NULL;
	for(; stance < STANCE_LAST; ++stance)
	{
		if (0 == strcmpi(szStance, ::GetStanceName((EStance)stance)))
			break;
	}

	if (((EStance)stance == STANCE_LAST) && (strlen(szStance) > 0))
	{
		CRY_ASSERT_TRACE(false, ("Invalid stance '%s'", szStance));
		return false;
	}

	CRY_ASSERT(stance >= STANCE_NULL);
	CRY_ASSERT(stance < STANCE_LAST);

	*pStance = (EStance)stance;
	return true;
}
Ejemplo n.º 2
0
bool STransition::ReadPseudoSpeedParam( const char* name, bool required, const struct IItemParamsNode*const pParams, float*const pPseudoSpeed ) const
{
	const char* szPseudoSpeed = pParams->GetAttribute(name);

	if (!szPseudoSpeed && !required)
		return false;

	CRY_ASSERT_TRACE(szPseudoSpeed, ("%s not found", name));
	if (!szPseudoSpeed)
		return false;

	// look for pseudospeed name (case insensitive)
	float pseudoSpeed = -1.0f;

	for(int iPseudoSpeed = 0; iPseudoSpeed < MovementTransitionsUtil::NUM_PSEUDOSPEEDS; ++iPseudoSpeed)
	{
		if (0 == strcmpi(szPseudoSpeed, MovementTransitionsUtil::s_pseudoSpeeds[iPseudoSpeed].name))
		{
			pseudoSpeed = MovementTransitionsUtil::s_pseudoSpeeds[iPseudoSpeed].value;
			break;
		}
	}

	if (pseudoSpeed == -1.0f)
	{
		CRY_ASSERT_TRACE(false, ("Invalid pseudospeed '%s'", szPseudoSpeed));
		return false;
	}

	*pPseudoSpeed = pseudoSpeed;
	return true;
}
Ejemplo n.º 3
0
//----------------------------------------------------------
void CSingleAllocTextBlock::Allocate()
{
	CRY_ASSERT_TRACE(m_mem == NULL, ("Already allocated memory but something's trying to allocate %u bytes more", m_sizeNeeded));
	m_mem = new char[m_sizeNeeded + MORE_SINGLE_ALLOC_TEXT_BLOCK_CHECKS];
	CRY_ASSERT_TRACE(m_mem != NULL, ("Failed to allocate %u bytes of memory!", m_sizeNeeded));

	SingleAllocTextBlockLog ("Allocated %u bytes of memory (saved %u bytes by reusing strings; number of unique strings found is %d/%d)", m_sizeNeeded, m_sizeNeededWithoutUsingDuplicates - m_sizeNeeded, m_reuseDuplicatedStringsNumUsed, m_reuseDuplicatedStringsArraySize);

	m_reuseDuplicatedStringsNumUsed = 0;

#if MORE_SINGLE_ALLOC_TEXT_BLOCK_CHECKS
	m_mem[m_sizeNeeded] = '@';
#endif

	CRY_ASSERT_TRACE(m_numBytesUsed == 0, ("Allocating memory but have apparently already used %u bytes!", m_numBytesUsed));
}
Ejemplo n.º 4
0
//----------------------------------------------------------
const char * CSingleAllocTextBlock::StoreText(const char * textIn, bool doDuplicateCheck)
{
	const char * reply = NULL;

	if (textIn)
	{
		reply = doDuplicateCheck ? FindDuplicate(textIn) : NULL;
		if (reply == NULL)
		{
			CRY_ASSERT_MESSAGE(m_mem != NULL, "No memory has been allocated!");
			if (cry_strncpy(m_mem + m_numBytesUsed, textIn, m_sizeNeeded - m_numBytesUsed))
			{
				reply = m_mem + m_numBytesUsed;
				m_numBytesUsed += strlen(reply) + 1;
				if (doDuplicateCheck)
				{
					RememberPossibleDuplicate(reply);
				}
			}
#ifndef _RELEASE
			else
			{
				GameWarning("Tried to store too much text in a single-alloc text block of size %" PRISIZE_T " (%" PRISIZE_T " bytes have already been used, no room for '%s')", m_sizeNeeded, m_numBytesUsed, textIn);
			}
#endif
		}
		SingleAllocTextBlockLog ("Storing a copy of '%s', now used %u/%u bytes, %u bytes left", textIn, m_numBytesUsed, m_sizeNeeded, m_sizeNeeded - m_numBytesUsed);
	}

	CRY_ASSERT_TRACE (m_numBytesUsed <= m_sizeNeeded, ("Counters have been set to invalid values! Apparently used %d/%d bytes!", m_numBytesUsed, m_sizeNeeded));

	return reply;
}
//-------------------------------------------------------------------------
/* static */ void CStatsEntityIdRegistry::ReadClassIds( XmlNodeRef xmlNode, uint16 &defaultId, TClassIdVec &vec )
{
	const char *pDefault;
	if (xmlNode->getAttr("default", &pDefault))
	{
		defaultId = atoi(pDefault);
	}

	const IEntityClassRegistry *pClassRegistry = gEnv->pEntitySystem->GetClassRegistry();
	const int numEntities = xmlNode->getChildCount();
	vec.reserve(numEntities);
	for (int i = 0; i < numEntities; ++ i)
	{
		XmlNodeRef xmlEntity = xmlNode->getChild(i);

		const char *pName;
		const char *pValue;
		if (xmlEntity->getAttr("name", &pName) && xmlEntity->getAttr("value", &pValue))
		{
			SClassId entity;
			entity.m_pClass = pClassRegistry->FindClass(pName);
			CRY_ASSERT_TRACE(entity.m_pClass, ("Failed to find class '%s' referenced in StatsEntityIds.xml", pName));
			entity.m_id = atoi(pValue);
			vec.push_back(entity);
		}
	}
}
Ejemplo n.º 6
0
//------------------------------------------------------------------------
float CGameRulesMPDamageHandling::CalcExplosionDamage(IEntity* entity, const ExplosionInfo &explosionInfo, float obstruction)
{
	// impact explosions directly damage the impact target
	if (explosionInfo.impact && explosionInfo.impact_targetId && explosionInfo.impact_targetId==entity->GetId())
	{
		return explosionInfo.damage;
	}

	float effect = 0.f;
	AABB entityAABB;

	entity->GetWorldBounds(entityAABB);

	float distanceSq = entityAABB.GetDistanceSqr(explosionInfo.pos);
	

	if (distanceSq <= explosionInfo.radius * explosionInfo.radius)
	{
		if (distanceSq <= explosionInfo.minRadius * explosionInfo.minRadius)
		{
			effect = 1.f;
		}
		else
		{
			effect = 1.f - (sqrtf(distanceSq) - explosionInfo.minRadius) / (explosionInfo.radius - explosionInfo.minRadius);
			effect *= effect;
		}
	}

	CRY_ASSERT_TRACE (effect >= 0.0f && effect <= 1.0f, ("Effectiveness of explosion should be between 0 and 1 but it's %.3f (distance = %.3f, minRadius=%.3f, maxRadius=%.3f)", effect, sqrtf(distanceSq), explosionInfo.minRadius, explosionInfo.radius));

	return explosionInfo.damage * effect * (1.0f - sqr(obstruction));
}
IAIActorProxy* CAIProxyManager::CreateActorProxy(EntityId entityID)
{
	CAIProxy *pResult = NULL;

	if (IGameObject* gameObject = CCryAction::GetCryAction()->GetGameObject(entityID))
	{
		pResult = new CAIProxy(gameObject);

		// (MATT) Check if this instance already has a proxy - right now there's no good reason to change proxies on an instance {2009/04/06}
		TAIProxyMap::iterator it = m_aiProxyMap.find(entityID);
		if (it != m_aiProxyMap.end())
		{
			CRY_ASSERT_TRACE(false, ("Entity ID %d already has an actor proxy! possible memory leak", entityID));
			it->second = pResult;
		}
		else
		{
			m_aiProxyMap.insert( std::make_pair(entityID,pResult) );
		}
	}
	else
	{
		GameWarning("Trying to create AIActorProxy for un-existent game object.");
	}

	return pResult;
}
Ejemplo n.º 8
0
bool STransition::ReadIntParam( const char* name, bool required, int min, int max, const struct IItemParamsNode*const pParams, int*const pI ) const
{
	int i;

	bool success = pParams->GetAttribute(name, i);

	if (!success && !required)
		return false;

	CRY_ASSERT_TRACE(success, ("%s not found", name));
	if (!success) return false;
	CRY_ASSERT_TRACE(i >= min, ("%s (%d) too small (should be > %d)", name, i, min));
	if (!(i >= min)) return false;
	CRY_ASSERT_TRACE(i <= max, ("%s (%d) too big (should be < %d)", name, i, max));
	if (!(i <= max)) return false;

	*pI = i;
	return true;
}
Ejemplo n.º 9
0
bool STransition::ReadFloatParam( const char* name, bool required, float min, float max, const struct IItemParamsNode*const pParams, float*const pF ) const
{
	float f;

	bool success = pParams->GetAttribute(name, f);

	if (!success && !required)
		return false;

	CRY_ASSERT_TRACE(success, ("%s not found", name));
	if (!success) return false;
	CRY_ASSERT_TRACE(f >= min, ("%s (%f) too small (should be > %f)", name, f, min));
	if (!(f >= min)) return false;
	CRY_ASSERT_TRACE(f <= max, ("%s (%f) too big (should be < %f)", name, f, max));
	if (!(f <= max)) return false;

	*pF = f;
	return true;
}
Ejemplo n.º 10
0
//-----------------------------------------------------------------------
const CSpectacularKill::SSpectacularKillParams* CSpectacularKill::GetParamsForClass( IEntityClass* pTargetClass ) const
{
	CRY_ASSERT_TRACE(m_pParams != NULL, ("Trying to get params from a spectacular kill object without params. Check if entity class %s has a param file in Scripts/actor/parameters", m_pOwner->GetEntityClassName()));
	if (m_pParams)
	{
		CRY_ASSERT(pTargetClass);

		TSpectacularKillParamsVector::const_iterator itEnd = m_pParams->paramsList.end();
		for (TSpectacularKillParamsVector::const_iterator it = m_pParams->paramsList.begin(); it != itEnd; ++it)
		{
			if (pTargetClass == it->pEnemyClass)
			{
				return &(*it);
			}
		}
	}

	return NULL;
}
Ejemplo n.º 11
0
void CSharedParamsManager::Reset()
{
#ifdef _DEBUG
	for(TRecordMap::const_iterator iRecord = m_records.begin(), iEndRecord = m_records.end(); iRecord != iEndRecord; ++ iRecord)
	{
		long	use_count = iRecord->second.use_count();

		CRY_ASSERT_TRACE(use_count == 1, ("Shared params structure '%s' is still referenced in %d place%s", m_names[iRecord->first].c_str(), use_count - 1, (use_count == 2) ? "" : "s"));
	}
#endif //_DEBUG

	// Ensure all memory is returned to the level heap.

	stl::free_container(m_records);

	stl::free_container(m_names);

	m_sizeOfSharedParams = 0;
}
Ejemplo n.º 12
0
void CPlayerStateUtil::FinalizeMovementRequest( CPlayer& player, const SActorFrameMovementParams & movement, SCharacterMoveRequest& request )
{
	//////////////////////////////////////////////////////////////////////////
	/// Remote players stuff...

	UpdateRemotePlayersInterpolation(player, movement, request);

	//////////////////////////////////////////////////////////////////////////
	///  Send the request to animated character

	if (player.m_pAnimatedCharacter)
	{
		request.allowStrafe = movement.allowStrafe;
		request.prediction = movement.prediction;

		CRY_ASSERT_TRACE(request.velocity.IsValid(), ("Invalid velocity %.2f %.2f %.2f for %s!", request.velocity.x, request.velocity.y, request.velocity.z, player.GetEntity()->GetEntityTextDescription()));

		NETINPUT_TRACE(player.GetEntityId(), request.rotation * FORWARD_DIRECTION);
		NETINPUT_TRACE(player.GetEntityId(), request.velocity);

#ifdef STATE_DEBUG
		player.DebugGraph_AddValue("ReqVelo", request.velocity.GetLength());
		player.DebugGraph_AddValue("ReqVeloX", request.velocity.x);
		player.DebugGraph_AddValue("ReqVeloY", request.velocity.y);
		player.DebugGraph_AddValue("ReqVeloZ", request.velocity.z);
		player.DebugGraph_AddValue("ReqRotZ", RAD2DEG(request.rotation.GetRotZ()));
#endif

		player.m_pAnimatedCharacter->AddMovement( request );
	}

	NETINPUT_TRACE(player.GetEntityId(), request.velocity);

	player.m_lastRequestedVelocity = request.velocity; 

	// reset the request for the next frame!
	InitializeMoveRequest( request );
}
Ejemplo n.º 13
0
bool CGameRulesSpawningBase::SvRequestRevive(EntityId playerId, EntityId preferredSpawnId)
{
	CRY_ASSERT_TRACE(0, ("CGameRulesSpawningBase::SvRequestRevive() is NOT implemented and shouldn't be called until it has been"));
	return false;
}
Ejemplo n.º 14
0
void CGameRulesSpawningBase::ClRequestRevive(EntityId playerId)
{
	CRY_ASSERT_TRACE(0, ("CGameRulesSpawningBase::ClRequestRevive() is NOT implemented and shouldn't be called until it has been"));
}
Ejemplo n.º 15
0
void CGameRulesSpawningBase::DisablePOI(EntityId entityId)
{
	CRY_ASSERT_TRACE(0, ("CGameRulesSpawningBase::DisablePOI() is NOT implemented and shouldn't be called until it has been"));
}
Ejemplo n.º 16
0
void CGameRulesSpawningBase::AddAvoidPOI(EntityId entityId, float avoidDistance, bool enabled, bool bStaticPOI)
{
	CRY_ASSERT_TRACE(0, ("CGameRulesSpawningBase::AddAvoidPOI() is NOT implemented and shouldn't be called until it has been"));
}
Ejemplo n.º 17
0
EntityId CGameRulesSpawningBase::GetSpawnLocation(EntityId playerId)
{
	CRY_ASSERT_TRACE(0, ("CGameRulesSpawningBase::GetSpawnLocation() is NOT implemented and shouldn't be called until it has been"));
	return 0;
}
Ejemplo n.º 18
0
bool CPlayerStateGround::CheckForVaultTrigger(CPlayer & player, float frameTime)
{
	const int enableVaultFromStandingCVar = g_pGameCVars->pl_ledgeClamber.enableVaultFromStanding;
	const bool doCheck = (enableVaultFromStandingCVar == 3) || ((enableVaultFromStandingCVar > 0) && player.m_jumpButtonIsPressed);

	if (doCheck)
	{
		SLedgeTransitionData ledgeTransition(LedgeId::invalid_id);
		const float zPos = player.GetEntity()->GetWorldPos().z;
		const bool ignoreMovement = (enableVaultFromStandingCVar == 2);

		if (CPlayerStateLedge::TryLedgeGrab(player, zPos, zPos, true, &ledgeTransition, ignoreMovement) && ledgeTransition.m_ledgeTransition != SLedgeTransitionData::eOLT_None)
		{
			CRY_ASSERT( LedgeId(ledgeTransition.m_nearestGrabbableLedgeId).IsValid() );
			const SLedgeInfo ledgeInfo = g_pGame->GetLedgeManager()->GetLedgeById( LedgeId(ledgeTransition.m_nearestGrabbableLedgeId) );
			
			CRY_ASSERT( ledgeInfo.IsValid() );

			if (ledgeInfo.AreAnyFlagsSet(kLedgeFlag_useVault|kLedgeFlag_useHighVault))
			{
#ifdef STATE_DEBUG

				if (g_pGameCVars->pl_ledgeClamber.debugDraw)
				{
					const char * transitionName = s_ledgeTransitionNames[ledgeTransition.m_ledgeTransition];

					IEntity* pEntity = gEnv->pEntitySystem->GetEntity(ledgeInfo.GetEntityId());
					CryWatch ("[LEDGEGRAB] $5%s nearest ledge: %s%s%s%s, transition=%s", player.GetEntity()->GetEntityTextDescription(), pEntity ? pEntity->GetEntityTextDescription() : "none", ledgeInfo.AreFlagsSet(kLedgeFlag_isThin) ? " THIN" : "", ledgeInfo.AreFlagsSet(kLedgeFlag_isWindow) ? " WINDOW" : "", ledgeInfo.AreFlagsSet(kLedgeFlag_endCrouched) ? " ENDCROUCHED" : "", transitionName);
				}

#endif

				if (player.m_jumpButtonIsPressed || enableVaultFromStandingCVar == 3)
				{
					ledgeTransition.m_comingFromOnGround=true;
					ledgeTransition.m_comingFromSprint=player.IsSprinting();

					SStateEventLedge ledgeEvent(ledgeTransition);
					player.StateMachineHandleEventMovement(ledgeEvent);
					return true;
				}
				else
				{
#ifdef STATE_DEBUG
					if (g_pGameCVars->pl_ledgeClamber.debugDraw)
					{
						const char * message = NULL;
						switch (ledgeTransition.m_ledgeTransition)
						{
							case SLedgeTransitionData::eOLT_VaultOnto:
							message = "CLIMB";
							break;

							case SLedgeTransitionData::eOLT_VaultOver:
							message = "VAULT";
							break;

							default:
							CRY_ASSERT_TRACE(0, ("Unexpected ledge transition #%d when trying to display HUD prompt for vault-from-standing!", ledgeTransition.m_ledgeTransition));
							break;
						}

						if (message)
						{
							const float textColor[4] = {1.f, 1.f, 1.f, 1.0f};
							const float bracketColor[4] = {0.7f, 0.7f, 0.7f, 1.0f};
							const float iconSize = 4.f;
							const float textSize = 2.f;
							const float iconColor[4] = {0.3f, 1.f, 0.3f, 1.0f};
							const char * iconText = "A";

							gEnv->pRenderer->Draw2dLabel((gEnv->pRenderer->GetWidth() * 0.5f), (gEnv->pRenderer->GetHeight() * 0.65f), iconSize, bracketColor, true, "( )");
							gEnv->pRenderer->Draw2dLabel((gEnv->pRenderer->GetWidth() * 0.5f), (gEnv->pRenderer->GetHeight() * 0.65f), iconSize, iconColor, true, "%s", iconText);
							gEnv->pRenderer->Draw2dLabel((gEnv->pRenderer->GetWidth() * 0.5f), (gEnv->pRenderer->GetHeight() * 0.72f), textSize, textColor, true, "%s", message);
						}
					}
#endif
				}
			}
		}
	}

	return false;
}
//-------------------------------------------------------------------------
uint16 CStatsEntityIdRegistry::GetGameModeId( const char *pModeName ) const
{
	const IEntityClass *pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(pModeName);
	CRY_ASSERT_TRACE(pClass, ("Failed to find class '%s'", pModeName));
	return GetGameModeId(pClass);
}
Ejemplo n.º 20
0
void CGameRulesSpawningBase::PerformRevive(EntityId playerId, int teamId, EntityId preferredSpawnId)
{
	CRY_ASSERT_TRACE(0, ("CGameRulesSpawningBase::PerformRevive() is NOT implemented and shouldn't be called until it has been"));
}
Ejemplo n.º 21
0
	void OnInitialise()
	{
#ifndef _RELEASE
		CRY_ASSERT_TRACE (0, ("Unexpected anim type %d (%s) for %s action", m_animType, s_onOffAnimTypeNames[m_animType], GetName()));
#endif
	}
Ejemplo n.º 22
0
void CGameRulesSpawningBase::ReviveAllPlayers(bool isReset, bool bOnlyIfDead)
{
	CRY_ASSERT_TRACE(0, ("CGameRulesSpawningBase::ReviveAllPlayers() is NOT implemented and shouldn't be called until it has been. Shouldn't be needed in singleplayer"));
}
Ejemplo n.º 23
0
bool STransition::ReadParams( ETransitionType _transitionType, const struct IItemParamsNode*const pParams )
{
	transitionType = _transitionType;

	animGraphSignal = pParams->GetAttribute("animGraphSignal");
	CRY_ASSERT_TRACE(animGraphSignal.length() > 0, ("animGraphSignal not found or empty"));
	if (!(animGraphSignal.length() > 0)) return false;

	pseudoSpeed = 0.0f;
	//if (!ReadFloatParam("pseudoSpeed", true, AISPEED_SLOW, AISPEED_SPRINT, pParams, &pseudoSpeed)) return false;
	if (!ReadPseudoSpeedParam("pseudoSpeed", true, pParams, &pseudoSpeed)) return false;

	stance = STANCE_NULL;
	if (!ReadStanceParam("stance", true, pParams, &stance)) return false;

	targetStance = STANCE_NULL;
	ReadStanceParam("targetStance", false, pParams, &targetStance);

	int iContext = 0; // default = don't care
	ReadIntParam("context", false, 0, INT_MAX, pParams, &iContext);
	context = (unsigned)iContext;

	minDistance = 0.0f;
	if (!ReadFloatParam("minDist", true, 0.0f, FLT_MAX, pParams, &minDistance)) return false;

	desiredTravelAngle = 0.0f;
	if (!ReadAngleParam("travelAngle", true, -gf_PI2, gf_PI2, pParams, &desiredTravelAngle)) return false;

	travelAngleTolerance = FLT_MAX;
	if (!ReadAngleParam("travelAngleTolerance", true, 0.0f, gf_PI2, pParams, &travelAngleTolerance)) return false;

	if (transitionType == eTT_Start)
	{
		maxDistance = FLT_MAX;
		prepareDistance = FLT_MAX;
		prepareTravelAngleTolerance = FLT_MAX;
		desiredArrivalAngle = 0.0f;
		arrivalAngleTolerance = FLT_MAX;
	}
	else
	{
		maxDistance = minDistance;
		if (!ReadFloatParam("maxDist", true, minDistance, FLT_MAX, pParams, &maxDistance)) return false;

		const float maxMovementPerFrame = 7.5f/30.0f; // 7.5m/s at 30fps gives you 25cm per frame
		minDistance -= maxMovementPerFrame/2;
		maxDistance = minDistance + maxMovementPerFrame; 

		prepareDistance = maxDistance;
		if (!ReadFloatParam("prepareDist", true, maxDistance, FLT_MAX, pParams, &prepareDistance)) return false;

		prepareTravelAngleTolerance = FLT_MAX;
		if (!ReadAngleParam("prepareTravelAngleTolerance", true, 0.0f, gf_PI2, pParams, &prepareTravelAngleTolerance)) return false;
	}

	if (transitionType == eTT_Stop)
	{
		desiredArrivalAngle = 0.0f;
		bool hasDesiredArrivalAngle = ReadAngleParam("arrivalAngle", false, -gf_PI2, gf_PI2, pParams, &desiredArrivalAngle);

		arrivalAngleTolerance = FLT_MAX;
		bool hasArrivalAngleTolerance = ReadAngleParam("arrivalAngleTolerance", false, 0.0f, gf_PI2, pParams, &arrivalAngleTolerance);

		CRY_ASSERT_MESSAGE(!hasDesiredArrivalAngle ||  hasArrivalAngleTolerance, "Transition has arrivalAngle but no arrivalAngleTolerance");
		CRY_ASSERT_MESSAGE( hasDesiredArrivalAngle || !hasArrivalAngleTolerance, "Transition has arrivalAngleTolerance but no arrivalAngle");
	}
	else
	{
		desiredTargetTravelAngle = 0.0f;
		bool hasDesiredTargetTravelAngle = ReadAngleParam("targetTravelAngle", false, -gf_PI2, gf_PI2, pParams, &desiredTargetTravelAngle);

		targetTravelAngleTolerance = FLT_MAX;
		bool hasTargetTravelAngleTolerance = ReadAngleParam("targetTravelAngleTolerance", false, 0.0f, gf_PI2, pParams, &targetTravelAngleTolerance);

		CRY_ASSERT_MESSAGE(!hasDesiredTargetTravelAngle ||  hasTargetTravelAngleTolerance, "Transition has targetTravelAngle but no targetTravelAngleTolerance");
		CRY_ASSERT_MESSAGE( hasDesiredTargetTravelAngle || !hasTargetTravelAngleTolerance, "Transition has targetTravelAngleTolerance but no targetTravelAngle");

		if (transitionType == eTT_DirectionChange)
		{
			desiredJukeAngle = 0.0f;
			if (!ReadAngleParam("jukeAngle", true, -gf_PI2, gf_PI2, pParams, &desiredJukeAngle)) return false;

			jukeAngleTolerance = FLT_MAX;
			if (!ReadAngleParam("jukeAngleTolerance", true, 0.0f, gf_PI2, pParams, &jukeAngleTolerance)) return false;
		}
		else // if (transitionType == eTT_Start)
		{
			desiredJukeAngle = 0.0f;
			jukeAngleTolerance = FLT_MAX;
		}
	}

	return true;
}