/* <1bd087> ../cstrike/dlls/vehicle.cpp:764 */ void CFuncVehicle::DeadEnd() { CPathTrack *pTrack = m_ppath; ALERT(at_aiconsole, "TRAIN(%s): Dead end ", STRING(pev->targetname)); if (pTrack != NULL) { CPathTrack *pNext; if (m_oldSpeed < 0) { do { pNext = pTrack->ValidPath(pTrack->GetPrevious(), TRUE); if (pNext != NULL) { pTrack = pNext; } } while (pNext != NULL); } else { do { pNext = pTrack->ValidPath(pTrack->GetNext(), TRUE); if (pNext != NULL) { pTrack = pNext; } } while (pNext != NULL); } } pev->velocity = g_vecZero; pev->avelocity = g_vecZero; if (pTrack != NULL) { ALERT(at_aiconsole, "at %s\n", STRING(pTrack->pev->targetname)); if (!FStringNull(pTrack->pev->netname)) { FireTargets(STRING(pTrack->pev->netname), this, this, USE_TOGGLE, 0); } } else ALERT(at_aiconsole, "\n"); }
// Assumes this is ALWAYS enabled CPathTrack *CPathTrack :: LookAhead( Vector *origin, float dist, int move ) { CPathTrack *pcurrent; float originalDist = dist; pcurrent = this; Vector currentPos = *origin; if ( dist < 0 ) // Travelling backwards through path { dist = -dist; while ( dist > 0 ) { Vector dir = pcurrent->pev->origin - currentPos; float length = dir.Length(); if ( !length ) { if ( !ValidPath(pcurrent->GetPrevious(), move) ) // If there is no previous node, or it's disabled, return now. { if ( !move ) Project( pcurrent->GetNext(), pcurrent, origin, dist ); return NULL; } pcurrent = pcurrent->GetPrevious(); } else if ( length > dist ) // enough left in this path to move { *origin = currentPos + (dir * (dist / length)); return pcurrent; } else { dist -= length; currentPos = pcurrent->pev->origin; *origin = currentPos; if ( !ValidPath(pcurrent->GetPrevious(), move) ) // If there is no previous node, or it's disabled, return now. return NULL; pcurrent = pcurrent->GetPrevious(); } } *origin = currentPos; return pcurrent; } else { while ( dist > 0 ) { if ( !ValidPath(pcurrent->GetNext(), move) ) // If there is no next node, or it's disabled, return now. { if ( !move ) Project( pcurrent->GetPrevious(), pcurrent, origin, dist ); return NULL; } Vector dir = pcurrent->GetNext()->pev->origin - currentPos; float length = dir.Length(); if ( !length && !ValidPath( pcurrent->GetNext()->GetNext(), move ) ) { if ( dist == originalDist ) // HACK -- up against a dead end return NULL; return pcurrent; } if ( length > dist ) // enough left in this path to move { *origin = currentPos + (dir * (dist / length)); return pcurrent; } else { dist -= length; currentPos = pcurrent->GetNext()->pev->origin; pcurrent = pcurrent->GetNext(); *origin = currentPos; } } *origin = currentPos; } return pcurrent; }
void CTeamTrainWatcher::FireGameEvent( IGameEvent *event ) { if ( IsDisabled() || !m_bHandleTrainMovement ) return; const char *pszEventName = event->GetName(); if ( FStrEq( pszEventName, "path_track_passed" ) ) { int iIndex = event->GetInt( "index" ); CPathTrack *pNode = dynamic_cast< CPathTrack* >( UTIL_EntityByIndex( iIndex ) ); if ( pNode ) { bool bHandleEvent = false; CPathTrack *pTempNode = m_hStartNode.Get(); // is this a node in the track we're watching? while ( pTempNode ) { if ( pTempNode == pNode ) { bHandleEvent = true; break; } pTempNode = pTempNode->GetNext(); } if ( bHandleEvent ) { // If we're receding and we've hit a node but the next node (going backwards) is disabled // the train is going to stop (like at the base of a downhill section) when we start forward // again we won't pass this node again so don't change our hill state based on this node. if ( m_bReceding ) { if ( pNode->GetPrevious() && pNode->GetPrevious()->IsDisabled() ) { return; } } int iHillType = pNode->GetHillType(); bool bUpdate = ( m_iCurrentHillType != iHillType ); if ( !bUpdate ) { // the hill settings are the same, but are we leaving an uphill or downhill segment? if ( m_iCurrentHillType != HILL_TYPE_NONE ) { // let's peek at the next node CPathTrack *pNextNode = pNode->GetNext(); if ( m_flCurrentSpeed < 0 ) { // we're going backwards pNextNode = pNode->GetPrevious(); } if ( pNextNode ) { int iNextHillType = pNextNode->GetHillType(); if ( m_iCurrentHillType != iNextHillType ) { // we're leaving an uphill or downhill segment...so reset our state until we pass the next node bUpdate = true; iHillType = HILL_TYPE_NONE; } } } } if ( bUpdate ) { m_iCurrentHillType = iHillType; HandleTrainMovement(); } } } } }