/** 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
/** Called when a kart is hit. * \param kart_id The world kart id of the kart that was hit. */ void ThreeStrikesBattle::kartHit(const int kart_id) { assert(kart_id >= 0); assert(kart_id < (int)m_karts.size()); // make kart lose a life m_kart_info[kart_id].m_lives--; // record event BattleEvent evt; evt.m_time = getTime(); evt.m_kart_info = m_kart_info; m_battle_events.push_back(evt); updateKartRanks(); // check if kart is 'dead' if (m_kart_info[kart_id].m_lives < 1) { m_karts[kart_id]->finishedRace(WorldStatus::getTime()); scene::ISceneNode** wheels = m_karts[kart_id]->getKartModel() ->getWheelNodes(); if(wheels[0]) wheels[0]->setVisible(false); if(wheels[1]) wheels[1]->setVisible(false); if(wheels[2]) wheels[2]->setVisible(false); if(wheels[3]) wheels[3]->setVisible(false); eliminateKart(kart_id, /*notify_of_elimination*/ true); m_insert_tire = 4; } const unsigned int NUM_KARTS = getNumKarts(); int num_karts_many_lives = 0; for (unsigned int n = 0; n < NUM_KARTS; ++n) { if (m_kart_info[n].m_lives > 1) num_karts_many_lives++; } // when almost over, use fast music if (num_karts_many_lives<=1 && !m_faster_music_active) { music_manager->switchToFastMusic(); m_faster_music_active = true; } scene::ISceneNode* kart_node = m_karts[kart_id]->getNode(); // FIXME: sorry for this ugly const_cast, irrlicht doesn't seem to allow // getting a writable list of children, wtf?? core::list<scene::ISceneNode*>& children = const_cast<core::list<scene::ISceneNode*>&>(kart_node->getChildren()); for (core::list<scene::ISceneNode*>::Iterator it = children.begin(); it != children.end(); it++) { scene::ISceneNode* curr = *it; if (core::stringc(curr->getName()) == "tire1") { curr->setVisible(m_kart_info[kart_id].m_lives >= 3); } else if (core::stringc(curr->getName()) == "tire2") { curr->setVisible(m_kart_info[kart_id].m_lives >= 2); } } // schedule a tire to be thrown away (but can't do it in this callback // because the caller is currently iterating the list of track objects) m_insert_tire++; core::vector3df wheel_pos(m_karts[kart_id]->getKartWidth()*0.5f, 0.0f, 0.0f); m_tire_position = kart_node->getPosition() + wheel_pos; m_tire_rotation = 0; if(m_insert_tire > 1) { m_tire_position = kart_node->getPosition(); m_tire_rotation = m_karts[kart_id]->getHeading(); } for(unsigned int i=0; i<4; i++) { m_tire_offsets[i] = m_karts[kart_id]->getKartModel() ->getWheelGraphicsPosition(i).toIrrVector(); m_tire_offsets[i].rotateXZBy(-m_tire_rotation / M_PI * 180 + 180); m_tire_radius[i] = m_karts[kart_id]->getKartModel() ->getWheelGraphicsRadius(i); } m_tire_dir = m_karts[kart_id]->getKartProperties()->getKartDir(); if(m_insert_tire == 5 && m_karts[kart_id]->isWheeless()) m_insert_tire = 0; } // kartHit