void Entity::FollowRoute() { AppDebugAssert(m_routeId != -1); Route *route = g_app->m_location->m_levelFile->GetRoute(m_routeId); if( g_app->Multiplayer() ) route = g_app->m_location->m_routingSystem.GetRoute( m_routeId ); if(!route) { m_routeId = -1; return; } if (m_routeWayPointId == -1) { m_routeWayPointId = 0; } WayPoint *waypoint = route->m_wayPoints.GetData(m_routeWayPointId); if( !waypoint ) { m_routeId = -1; return; } SetWaypoint ( waypoint->GetPos() ); Vector3 targetVect = waypoint->GetPos() - m_pos; m_spawnPoint = waypoint->GetPos(); if (waypoint->m_type != WayPoint::TypeBuilding && targetVect.Mag() < m_routeTriggerDistance ) { m_routeWayPointId++; if (m_routeWayPointId >= route->m_wayPoints.Size()) { m_routeWayPointId = -1; m_routeId = -1; } } // // If its a building instead of a 3D pos, this unit will never // get to the next waypoint. A new unit is created when the unit // enters the teleport, and taht new unit will automatically // continue towards the next waypoint instead. // }
bool Nuke::Update() { // // Are we disarmed? if( m_currentState == 1 && m_stateTimer <= 0 ) { if( m_teamId == g_app->GetWorld()->m_myTeamId ) { char message[64]; sprintf( message, LANGUAGEPHRASE("message_disarmed") ); g_app->GetWorld()->AddWorldMessage( m_longitude, m_latitude, m_teamId, message, WorldMessage::TypeObjectState ); } return true; } // // Is our waypoint changing? Fixed timePerUpdate = SERVER_ADVANCE_PERIOD * g_app->GetWorld()->GetTimeScaleFactor(); if( m_newLongitude != 0 || m_newLatitude != 0 ) { Fixed factor1 = m_turnRate * timePerUpdate * 2; Fixed factor2 = 1 - factor1; m_targetLongitude = ( m_newLongitude * factor1 ) + ( m_targetLongitude * factor2 ); m_targetLatitude = ( m_newLatitude * factor1 ) + ( m_targetLatitude * factor2 ); if( ( m_targetLongitude - m_newLongitude ).abs() < 1 && ( m_targetLatitude - m_newLatitude ).abs() < 1 ) { SetWaypoint( m_newLongitude, m_newLatitude ); m_newLongitude = 0; m_newLatitude = 0; } } // // Move towards target Vector3<Fixed> target( m_targetLongitude, m_targetLatitude, 0 ); Vector3<Fixed> pos( m_longitude, m_latitude, 0 ); Fixed remainingDistance = (target - pos).Mag(); Fixed fractionDistance = 1 - remainingDistance / m_totalDistance; Vector3<Fixed> front = (target - pos).Normalise(); Fixed fractionNorth = 5 * m_latitude.abs() / ( 200 / 2 ); fractionNorth = max( fractionNorth, 3 ); front.RotateAroundZ( Fixed::PI / (fractionNorth * m_curveDirection) ); front.RotateAroundZ( fractionDistance * (-m_curveDirection * Fixed::PI/fractionNorth) ); if( pos.y > 85 ) { // We are dangerously far north // Make sure we dont go off the top of the world Fixed extremeFractionNorth = (pos.y - 85) / 15; Clamp( extremeFractionNorth, Fixed(0), Fixed(1) ); front.y *= ( 1 - extremeFractionNorth ); front.Normalise(); } m_vel = Vector3<Fixed>(front * (m_speed/2 + m_speed/2 * fractionDistance * fractionDistance)); Fixed newLongitude = m_longitude + m_vel.x * timePerUpdate; Fixed newLatitude = m_latitude + m_vel.y * timePerUpdate; Fixed newDistance = g_app->GetWorld()->GetDistance( newLongitude, newLatitude, m_targetLongitude, m_targetLatitude); if( newLongitude <= -180 || newLongitude >= 180 ) { m_longitude = newLongitude; CrossSeam(); newLongitude = m_longitude; newDistance = g_app->GetWorld()->GetDistance( newLongitude, newLatitude, m_targetLongitude, m_targetLatitude ); } if( newDistance < 2 && newDistance >= remainingDistance ) { m_targetLongitude = 0; m_targetLatitude = 0; m_vel.Zero(); g_app->GetWorld()->CreateExplosion( m_teamId, m_longitude, m_latitude, 100 ); g_soundSystem->TriggerEvent( SoundObjectId(m_objectId), "Detonate" ); return true; } else { m_range -= Vector3<Fixed>( m_vel.x * Fixed(timePerUpdate), m_vel.y * Fixed(timePerUpdate), 0 ).Mag(); if( m_range <= 0 ) { m_life = 0; m_lastHitByTeamId = -1; g_app->GetWorld()->AddOutOfFueldMessage( m_objectId ); } m_longitude = newLongitude; m_latitude = newLatitude; } return MovingObject::Update(); }