// $Id$ // // SuperTuxKart - a fun racing game with go-kart // Copyright (C) 2004-2006 Ingo Ruhnke // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 3 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include #include "file_manager.hpp" #include "string_utils.hpp" #include "kart_properties_manager.hpp" #include "kart_properties.hpp" #include "translation.hpp" #include "user_config.hpp" #include "unlock_manager.hpp" #if defined(WIN32) && !defined(__CYGWIN__) # define snprintf _snprintf #endif KartPropertiesManager *kart_properties_manager=0; KartPropertiesManager::KartPropertiesManager() { m_all_groups.clear(); } // KartPropertiesManager //----------------------------------------------------------------------------- KartPropertiesManager::~KartPropertiesManager() { for(KartPropertiesVector::iterator i = m_karts_properties.begin(); i != m_karts_properties.end(); ++i) delete *i; } // ~KartPropertiesManager //----------------------------------------------------------------------------- void KartPropertiesManager::removeTextures() { for(KartPropertiesVector::iterator i = m_karts_properties.begin(); i != m_karts_properties.end(); ++i) { delete *i; } m_karts_properties.clear(); callback_manager->clear(CB_KART); } // removeTextures //----------------------------------------------------------------------------- void KartPropertiesManager::loadKartData(bool dont_load_models) { m_max_steer_angle = -1.0f; std::set result; file_manager->listFiles(result, file_manager->getKartDir(), /*is_full_path*/ true); // Find out which characters are available and load them for(std::set::iterator i = result.begin(); i != result.end(); ++i) { std::string kart_file; try { kart_file = file_manager->getKartFile((*i)+".kart"); } catch (std::exception& e) { (void)e; // remove warning about unused variable continue; } FILE *f=fopen(kart_file.c_str(),"r"); if(!f) continue; fclose(f); KartProperties* kp = new KartProperties(); kp->load(kart_file, "tuxkart-kart", dont_load_models); m_karts_properties.push_back(kp); m_kart_available.push_back(true); if(kp->getMaxSteerAngle(0) > m_max_steer_angle) { m_max_steer_angle = kp->getMaxSteerAngle(0); } const std::vector& groups=kp->getGroups(); for(unsigned int g=0; ggetIdent() == ident) return i-m_karts_properties.begin(); } char msg[MAX_ERROR_MESSAGE_LENGTH]; snprintf(msg, sizeof(msg), "KartPropertiesManager: Couldn't find kart: '%s'", ident.c_str()); throw std::runtime_error(msg); } // getKartId //----------------------------------------------------------------------------- const KartProperties* KartPropertiesManager::getKart(const std::string &ident) const { for(KartPropertiesVector::const_iterator i = m_karts_properties.begin(); i != m_karts_properties.end(); ++i) { if ((*i)->getIdent() == ident) return *i; } return NULL; } // getKart //----------------------------------------------------------------------------- const KartProperties* KartPropertiesManager::getKartById(int i) const { if (i < 0 || i >= int(m_karts_properties.size())) return NULL; return m_karts_properties[i]; } // getKartById //----------------------------------------------------------------------------- /** Returns a list of all available kart identifiers. */ std::vector KartPropertiesManager::getAllAvailableKarts() const { std::vector all; for(KartPropertiesVector::const_iterator i = m_karts_properties.begin(); i != m_karts_properties.end(); ++i) { if(m_kart_available[i-m_karts_properties.begin()]) all.push_back((*i)->getIdent()); } return all; } // getAllAvailableKarts //----------------------------------------------------------------------------- /** Marks all karts except the ones listed in the string vector to be * unavailable. This function is used on a client when receiving the list of * karts from a client to mark all other karts as unavailable. * \param karts List of karts that are available on a client. */ void KartPropertiesManager::setUnavailableKarts(std::vector karts) { for(KartPropertiesVector::const_iterator i = m_karts_properties.begin(); i != m_karts_properties.end(); ++i) { if(!m_kart_available[i-m_karts_properties.begin()]) continue; if(std::find(karts.begin(), karts.end(), (*i)->getIdent()) == karts.end()) { m_kart_available[i-m_karts_properties.begin()]=false; fprintf(stderr, "Kart '%s' not available on all clients, disabled.\n", (*i)->getIdent().c_str()); } // kart not in list } // for i in m_kart_properties } // setUnavailableKarts //----------------------------------------------------------------------------- /** Returns the (global) index of the n-th kart of a given group. If there is * no such kart, -1 is returned. */ int KartPropertiesManager::getKartByGroup(const std::string& group, int n) const { int count=0; for(KartPropertiesVector::const_iterator i = m_karts_properties.begin(); i != m_karts_properties.end(); ++i) { std::vector groups=(*i)->getGroups(); if (std::find(groups.begin(), groups.end(), group)==groups.end()) continue; if(count==n) return (int)(i-m_karts_properties.begin()); count=count+1; } return -1; } // getKartByGroup //----------------------------------------------------------------------------- bool KartPropertiesManager::testAndSetKart(int kartid) { if(!kartAvailable(kartid)) return false; m_selected_karts.push_back(kartid); return true; } // testAndSetKart //----------------------------------------------------------------------------- /** Returns true if a kart is available to be selected. A kart is available to * be selected if it is available on all clients (i.e. m_kart_available is * true), not yet selected, and not locked. */ bool KartPropertiesManager::kartAvailable(int kartid) { if(!m_kart_available[kartid]) return false; std::vector::iterator it; for (it = m_selected_karts.begin(); it < m_selected_karts.end(); it++) { if ( kartid == *it) return false; } const KartProperties *kartprop=getKartById(kartid); if(unlock_manager->isLocked(kartprop->getIdent())) return false; return true; } // testAndSetKart //----------------------------------------------------------------------------- /** Sets a kart to be selected by specifying the identifier (name) of the kart. * \param kart_name Name of the kart. */ void KartPropertiesManager::selectKartName(const std::string &kart_name) { int kart_id = getKartId(kart_name); selectKart(kart_id); } // selectKartName //----------------------------------------------------------------------------- /** Returns a list of randomly selected karts. This list firstly contains * karts in the currently selected group, but which are not in the list * of 'existing karts'. If not enough karts are available in the current * group, karts from all other groups are used to fill up the list. * This is used by the race manager to select the AI karts. * \param count Number of karts to select randomly. * \param existing_karst List of karts that should not be used. This is the * list of karts selected by the players. */ std::vector KartPropertiesManager::getRandomKartList(int count, RemoteKartInfoList& existing_karts) { std::vector random_karts; // First: set up flags (based on global kart // index) for which karts are already used // ----------------------------------------- std::vector used; used.resize(getNumberOfKarts(), false); std::vector all_karts; for(unsigned int i=0; i karts = getKartsInGroup(user_config->m_kart_group); std::vector::iterator k; // Remove karts that are already used or generally not available // (i.e. locked or not available on all clients) for(unsigned int i=0; i0 && karts.size()>0) { used[karts.back()] = true; random_karts.push_back(m_karts_properties[karts.back()]->getIdent()); karts.pop_back(); count --; } if(count==0) return random_karts; // Not enough karts in chosen group, so fill the rest with arbitrary karts // ----------------------------------------------------------------------- // First create an index list with all unused karts. karts.clear(); for(unsigned int i=0; i0 && karts.size()>0) { random_karts.push_back(m_karts_properties[karts.back()]->getIdent()); karts.pop_back(); count --; } // There should always be enough karts assert(count==0); return random_karts; } // getRandomKartList /* EOF */