/** The battle is over if only one kart is left, or no player kart. */ bool ThreeStrikesBattle::isRaceOver() { // for tests : never over when we have a single player there :) if (race_manager->getNumPlayers() < 2) { return false; } return getCurrentNumKarts()==1 || getCurrentNumPlayers()==0; } // isRaceOver
/** The follow the leader race is over if there is only one kart left (plus * the leader), or if all (human) players have been eliminated. */ bool FollowTheLeaderRace::isRaceOver() { bool is_over = (getCurrentNumKarts()==2 || getCurrentNumPlayers()==0); if (is_over) { if (m_is_over_delay < 0.0f) { return true; } else { m_is_over_delay -= GUIEngine::getLatestDt(); return false; } } else { return false; } } // isRaceOver
unsigned int WorldWithRank::getRescuePositionIndex(AbstractKart *kart) { const int start_spots_amount = getTrack()->getNumberOfStartPositions(); assert(start_spots_amount > 0); float largest_accumulated_distance_found = -1; int furthest_id_found = -1; for(int n=0; n<start_spots_amount; n++) { const btTransform &s = getStartTransform(n); const Vec3 &v=s.getOrigin(); float accumulated_distance = .0f; bool spawn_point_clear = true; for(unsigned int k=0; k<getCurrentNumKarts(); k++) { if(kart->getWorldKartId()==k) continue; float abs_distance2 = (getKart(k)->getXYZ()-v).length2(); const float CLEAR_SPAWN_RANGE2 = 5*5; if( abs_distance2 < CLEAR_SPAWN_RANGE2) { spawn_point_clear = false; break; } accumulated_distance += sqrt(abs_distance2); } if(accumulated_distance > largest_accumulated_distance_found && spawn_point_clear) { furthest_id_found = n; largest_accumulated_distance_found = accumulated_distance; } } assert(furthest_id_found != -1); return furthest_id_found; } // getRescuePositionIndex
/** Called when a kart must be eliminated. */ void FollowTheLeaderRace::countdownReachedZero() { if(m_leader_intervals.size()>1) m_leader_intervals.erase(m_leader_intervals.begin()); WorldStatus::setTime(m_leader_intervals[0]); // If the leader kart is not the first kart, remove the first // kart, otherwise remove the last kart. int position_to_remove = m_karts[0]->getPosition()==1 ? getCurrentNumKarts() : 1; AbstractKart *kart = getKartAtPosition(position_to_remove); if(!kart || kart->isEliminated()) { fprintf(stderr,"Problem with removing leader: position %d not found\n", position_to_remove); for(unsigned int i=0; i<m_karts.size(); i++) { fprintf(stderr,"kart %d: eliminated %d position %d\n", i,m_karts[i]->isEliminated(), m_karts[i]->getPosition()); } // for i } // else { if(UserConfigParams::m_ftl_debug) { printf("[ftl] Eliminiating kart '%s' at position %d.\n", kart->getIdent().c_str(), position_to_remove); } eliminateKart(kart->getWorldKartId()); // In case that the kart on position 1 was removed, we have // to set the correct position (which equals the remaining // number of karts) for the removed kart, as well as recompute // the position for all other karts if(position_to_remove==1) { // We have to add 1 to the number of karts to get the correct // position, since the eliminated kart was already removed // from the value returned by getCurrentNumKarts (and we have // to remove the kart before we can call updateRacePosition). // Note that we can not call WorldWithRank::setKartPosition // here, since it would not properly support debugging kart // ranks (since this kart would get its position set again // in updateRacePosition). We only set the rank of the eliminated // kart, and updateRacePosition will then call setKartPosition // for the now eliminated kart. kart->setPosition(getCurrentNumKarts()+1); updateRacePosition(); } // Time doesn't make any sense in FTL (and it is not displayed) kart->finishedRace(-1.0f); // Move any camera for this kart to the leader, facing backwards, // so that the eliminated player has something to watch. if (race_manager->getNumPlayers() > 1) { for(unsigned int i=0; i<Camera::getNumCameras(); i++) { Camera *camera = Camera::getCamera(i); if(camera->getKart()==kart) { camera->setMode(Camera::CM_LEADER_MODE); camera->setKart(getKart(0)); } } // for i<number of cameras } } // if kart to eliminate exists // almost over, use fast music if(getCurrentNumKarts()==3) { music_manager->switchToFastMusic(); } if (isRaceOver()) { // Handle special FTL situation: the leader is kart number 3 when // the last kart gets eliminated. In this case kart on position 1 // is eliminated, and the kart formerly on position 2 is on // position 1, the leader now position 2. In this case the kart // on position 1 would get more points for this victory. So if // this is the case, change the position if(m_karts[0]->getPosition()!=1) { // Adjust the position of all still driving karts that // are ahead of the leader by +1, and move the leader // to position 1. for (unsigned int i=1; i<m_karts.size(); i++) { if(!m_karts[i]->hasFinishedRace() && !m_karts[i]->isEliminated() && m_karts[i]->getPosition()<m_karts[0]->getPosition()) { m_karts[i]->setPosition(m_karts[i]->getPosition()+1); } } m_karts[0]->setPosition(1); } // Mark all still racing karts to be finished. for (unsigned int n=0; n<m_karts.size(); n++) { if (!m_karts[n]->isEliminated() && !m_karts[n]->hasFinishedRace()) { m_karts[n]->finishedRace(getTime()); } } } // End of race is detected from World::updateWorld() } // countdownReachedZero
/** Moves a kart to its rescue position. * \param kart The kart that was rescued. */ void SoccerWorld::moveKartAfterRescue(AbstractKart* kart) { // find closest point to drop kart on World *world = World::getWorld(); const int start_spots_amount = world->getTrack()->getNumberOfStartPositions(); assert(start_spots_amount > 0); float largest_accumulated_distance_found = -1; int furthest_id_found = -1; const float kart_x = kart->getXYZ().getX(); const float kart_z = kart->getXYZ().getZ(); for(int n=0; n<start_spots_amount; n++) { // no need for the overhead to compute exact distance with sqrt(), // so using the 'manhattan' heuristic which will do fine enough. const btTransform &s = world->getTrack()->getStartTransform(n); const Vec3 &v=s.getOrigin(); float accumulatedDistance = .0f; bool spawnPointClear = true; for(unsigned int k=0; k<getCurrentNumKarts(); k++) { const AbstractKart *currentKart = World::getWorld()->getKart(k); const float currentKart_x = currentKart->getXYZ().getX(); const float currentKartk_z = currentKart->getXYZ().getZ(); if(kart_x!=currentKart_x && kart_z !=currentKartk_z) { float absDistance = fabs(currentKart_x - v.getX()) + fabs(currentKartk_z - v.getZ()); if(absDistance < CLEAR_SPAWN_RANGE) { spawnPointClear = false; break; } accumulatedDistance += absDistance; } } if(largest_accumulated_distance_found < accumulatedDistance && spawnPointClear) { furthest_id_found = n; largest_accumulated_distance_found = accumulatedDistance; } } assert(furthest_id_found != -1); const btTransform &s = world->getTrack()->getStartTransform(furthest_id_found); const Vec3 &xyz = s.getOrigin(); kart->setXYZ(xyz); kart->setRotation(s.getRotation()); //position kart from same height as in World::resetAllKarts btTransform pos; pos.setOrigin(kart->getXYZ()+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f)); pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 0 /* angle */) ); kart->getBody()->setCenterOfMassTransform(pos); //project kart to surface of track bool kart_over_ground = m_track->findGround(kart); if (kart_over_ground) { //add vertical offset so that the kart starts off above the track float vertical_offset = kart->getKartProperties()->getVertRescueOffset() * kart->getKartHeight(); kart->getBody()->translate(btVector3(0, vertical_offset, 0)); } else { Log::warn("[SoccerWorld]", " Invalid position after rescue for kart %s on track %s.", kart->getIdent().c_str(), m_track->getIdent().c_str()); } } // moveKartAfterRescue