Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/bindermFS16/src/orxonox/LevelManager.cc @ 11186

Last change on this file since 11186 was 11186, checked in by binderm, 8 years ago

LevelStatus and levelmanager in two files, LevelStatus saves and changes the actual campaign progress

  • Property svn:eol-style set to native
File size: 13.6 KB
RevLine 
[2072]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
[7802]25 *      Damian 'Mozork' Frick
[2072]26 *
27 */
28
[7804]29/**
30    @file LevelManager.cc
31    @brief Implementation of the LevelManager singleton.
32*/
33
[2072]34#include "LevelManager.h"
35
[3196]36#include <map>
[3280]37
[10624]38#include "core/singleton/ScopedSingletonIncludes.h"
39#include "core/commandline/CommandLineIncludes.h"
[9667]40#include "core/config/ConfigValueIncludes.h"
41#include "core/CoreIncludes.h"
[7648]42#include "core/ClassTreeMask.h"
[3370]43#include "core/Loader.h"
[6417]44#include "core/Resource.h"
[7648]45#include "core/XMLFile.h"
[7802]46#include "Level.h"
[2171]47#include "PlayerManager.h"
[2072]48
[11186]49
[2072]50namespace orxonox
51{
[11173]52
[11186]53//Mission endmission true
54    //check if index level is activated...
55    int LevelManager::missionactivate(int index)
[11173]56    {
[11186]57        updateAllLevelStatus();
58        int activated = allLevelStatus_[index].activated;
59        return activated;
[11173]60    }
61
[11186]62    void LevelManager::updatewon(int lastwon)
63    {
64        allLevelStatus_[lastwon].won=true;
[11173]65
[11186]66    }
[11180]67
[11186]68    void LevelManager::updateAllLevelStatus()
[11173]69    {
[11186]70        for(unsigned int i =0;i<allLevelStatus_.size();i++)
[11180]71        {
[11186]72            if(allLevelStatus_[i].won)
73            {
74                allLevelStatus_[i].activated=1;
75                std::vector<int> nextLevels=allLevelStatus_[i].nextLevels;
76                for(unsigned int j=i+1;j<allLevelStatus_.size();j++)
77                {
78                    allLevelStatus_[j].activated=nextLevels[j];
79                }
80            }
81        }
[11173]82    }
83
[11180]84    //updates the won variable of the corresponding LevelStatus in allLevelStatus_
[11186]85    void LevelManager::setLevelStatus(const std::string& LevelWon)
[11173]86    {
[11186]87        ModifyConfigValue(lastWonMission_, set, LevelWon); 
[11173]88    }
89
[11186]90
[11180]91    //build up allLevelStatus
92    //has to be done once per game (not per level)
93    //all connections between the levels are saved in here
94    void LevelManager::buildallLevelStatus()
95    {
96        LevelStatus level;
[11186]97        allLevelStatus_.assign (campaignMissions_.size(),level);
98        allLevelStatus_[0].activated=1;
99        //allLevelStatus_[0].won=true;
[11173]100
[11186]101
102        allLevelStatus_[0].nextLevels.push_back(1);
103        allLevelStatus_[0].nextLevels.push_back(1);
104        allLevelStatus_[0].nextLevels.push_back(0);
105        allLevelStatus_[0].nextLevels.push_back(0);
106        allLevelStatus_[0].nextLevels.push_back(0);
107        allLevelStatus_[0].nextLevels.push_back(0);
108        allLevelStatus_[0].nextLevels.push_back(0);
109
110        allLevelStatus_[1].nextLevels.push_back(1);
[11181]111        allLevelStatus_[1].nextLevels.push_back(2);
112        allLevelStatus_[1].nextLevels.push_back(1);
[11186]113        allLevelStatus_[1].nextLevels.push_back(0);
114        allLevelStatus_[1].nextLevels.push_back(0);
115        allLevelStatus_[1].nextLevels.push_back(0);
116        allLevelStatus_[1].nextLevels.push_back(0);
[11181]117
[11186]118        allLevelStatus_[2].nextLevels.push_back(2);
119        allLevelStatus_[2].nextLevels.push_back(1);
120        allLevelStatus_[2].nextLevels.push_back(0);
121        allLevelStatus_[2].nextLevels.push_back(0);
122        allLevelStatus_[2].nextLevels.push_back(1);
123        allLevelStatus_[2].nextLevels.push_back(0);
124        allLevelStatus_[2].nextLevels.push_back(0);
[11181]125
[11186]126
127
[11180]128    }
129
130
131
[3280]132    SetCommandLineArgument(level, "").shortcut("l").information("Default level file (overrides LevelManager::defaultLevelName_ configValue)");
133
[10624]134    ManageScopedSingleton(LevelManager, ScopeID::ROOT, false);
[2072]135
[10624]136    RegisterAbstractClass(LevelManager).inheritsFrom<Configurable>();
137
[7802]138    /**
139    @brief
140        Constructor. Registers the object, sets config values and initializes variables.
141    */
[2072]142    LevelManager::LevelManager()
143    {
[9667]144        RegisterObject(LevelManager);
[3280]145        this->setConfigValues();
146
[11173]147
148
[3280]149        // check override
[6021]150        if (!CommandLineParser::getArgument("level")->hasDefaultValue())
[3280]151        {
[9550]152            ModifyConfigValue(defaultLevelName_, tset, CommandLineParser::getValue("level").get<std::string>());
[3280]153        }
[7648]154
155        this->compileAvailableLevelList();
[7802]156        this->nextIndex_ = 0;
157        this->nextLevel_ = this->availableLevels_.begin();
[11173]158
[11180]159        buildallLevelStatus();
[2072]160    }
161
[11173]162
[2072]163    LevelManager::~LevelManager()
164    {
[8079]165        // Delete all the LevelInfoItem objects because the LevelManager created them
[11071]166        for (LevelInfoItem* info : availableLevels_)
167            info->destroy();
[2072]168    }
169
[7802]170    /**
171    @brief
172        Set the config values for this object.
173    */
[3280]174    void LevelManager::setConfigValues()
175    {
[8891]176        SetConfigValue(defaultLevelName_, "missionOne.oxw")
[6417]177            .description("Sets the pre selection of the level in the main menu.");
[11186]178        SetConfigValue(lastWonMission_,  "")
[10258]179            .description("The last finished mission of a campaign");
180        SetConfigValue(campaignMissions_,  std::vector<std::string>())
181            .description("The list of missions in the campaign");
[11186]182        SetConfigValue(test_,  std::vector<int>())
183            .description("The list of missions and their statuses");
184           
[3280]185    }
186
[7802]187    /**
[10258]188     * @brief Stores the argument in the corresponding config value.
189     */
[11186]190/*    void LevelManager::setLastFinishedCampaignMission(const std::string& lastFinishedCampaignMission)
[10258]191    {
[11186]192        ModifyConfigValue(lastWonMission_, set, lastFinishedCampaignMission);
[10258]193    }
[11186]194*/
[10258]195
[11173]196
[10258]197    /**
[7802]198    @brief
199        Request activity for the input Level.
200        The Level will be added to the list of Levels whose activity is requested. The list is accessed in a FIFO manner.
201        If the Level is the only Level in the list it will be immediately activated. If not it will be activated as soon as it reaches the front of the list.
202    @param level
203        A pointer to the Level whose activity is requested.
204    */
[2072]205    void LevelManager::requestActivity(Level* level)
206    {
[7802]207        assert( std::find(this->levels_.begin(), this->levels_.end(), level)==this->levels_.end() );
208        // If the level is already in list.
209        if( std::find(this->levels_.begin(), this->levels_.end(), level)!=this->levels_.end() )
210            return;
211        // If it isn't insert it at the back.
212        this->levels_.push_back(level);
213        // If it is the only level in the list activate it.
214        if (this->levels_.size() == 1)
[2072]215            this->activateNextLevel();
216    }
217
[7802]218    /**
219    @brief
220        Release activity for the input Level.
221        Removes the Level from the list. If the Level was the one currently active, it is deactivated and the next Level in line is activated.
222    @param level
223        A pointer to the Level whose activity is to be released.
224    */
[2072]225    void LevelManager::releaseActivity(Level* level)
226    {
[7802]227        if (this->levels_.size() > 0)
[2072]228        {
[7802]229            // If the level is the active level in the front of the list.
230            if (this->levels_.front() == level)
[2072]231            {
[7802]232                // Deactivate it, remove it from the list and activate the next level in line.
[2072]233                level->setActive(false);
[7802]234                this->levels_.pop_front();
[2072]235                this->activateNextLevel();
236            }
[7802]237            else // Else just remove it from the list.
238                this->levels_.erase(std::find(this->levels_.begin(), this->levels_.end(), level));
[2072]239        }
240    }
241
[7802]242    /**
243    @brief
244        Get the currently active Level.
245    @return
[11071]246        Returns a pointer to the currently active level or nullptr if there currently are no active Levels.
[7802]247    */
[2072]248    Level* LevelManager::getActiveLevel()
249    {
[7802]250        if (this->levels_.size() > 0)
251            return this->levels_.front();
[2072]252        else
[11071]253            return nullptr;
[2072]254    }
255
[7802]256    /**
257    @brief
258        Activate the next Level.
259    */
[2072]260    void LevelManager::activateNextLevel()
261    {
[7802]262        if (this->levels_.size() > 0)
[2072]263        {
[8891]264            // Activate the level that is the first in the list of levels whose activity has been requested.
[7802]265            this->levels_.front()->setActive(true);
266            // Make every player enter the newly activated level.
[11071]267            for (const auto& mapEntry : PlayerManager::getInstance().getClients())
268                this->levels_.front()->playerEntered(mapEntry.second);
[2072]269        }
270    }
[3280]271
[7802]272    /**
273    @brief
274        Set the default Level.
275    @param levelName
276        The filename of the default Level.
277    */
[3280]278    void LevelManager::setDefaultLevel(const std::string& levelName)
279    {
280        ModifyConfigValue(defaultLevelName_, set, levelName);
281    }
282
[7802]283    /**
284    @brief
285        Get the number of available Levels.
286        Also updates the list of available Levels.
287    @return
288        Returns the number of available Levels.
289    */
[7648]290    unsigned int LevelManager::getNumberOfLevels()
[3370]291    {
[7648]292        this->updateAvailableLevelList();
293
294        return this->availableLevels_.size();
295    }
296
[7802]297    /**
298    @brief
299        Get the LevelInfoItem at the given index in the list of available Levels.
300        The LevelInfoItems are sorted in alphabetical order accoridng to the name of the Level.
301        This method is most efficiently called with consecutive indices (or at least ascending indices).
[7804]302    @param index
303        The index of the item that should be returned.
[7802]304    @return
305        Returns a pointer to the LevelInfoItem at the given index.
306    */
307    LevelInfoItem* LevelManager::getAvailableLevelListItem(unsigned int index)
[7648]308    {
[7804]309        if(index >= this->availableLevels_.size())
[11071]310            return nullptr;
[7802]311
312        // If this index directly follows the last we can optimize a lot.
313        if(index == this->nextIndex_)
314        {
315            this->nextIndex_++;
316            std::set<LevelInfoItem*, LevelInfoCompare>::iterator it = this->nextLevel_;
317            this->nextLevel_++;
318            return *it;
319        }
[3370]320        else
[7648]321        {
[7802]322            // If this index is bigger than the last, we can optimize a little.
[7839]323            if(index < this->nextIndex_)
[7802]324            {
325                this->nextIndex_ = 0;
326                this->nextLevel_ = this->availableLevels_.begin();
327            }
[8706]328
[7802]329            while(this->nextIndex_ != index)
330            {
331                this->nextIndex_++;
332                this->nextLevel_++;
333            }
334            this->nextIndex_++;
335            std::set<LevelInfoItem*, LevelInfoCompare>::iterator it = this->nextLevel_;
336            this->nextLevel_++;
337            return *it;
[7648]338        }
[3370]339    }
340
[7802]341    /**
342    @brief
343        Compile the list of available Levels.
344        Iterates over all *.oxw files, loads the LevelInfo objects in them and from that it creates the LevelInfoItems which are inserted in a list.
345    */
[3370]346    void LevelManager::compileAvailableLevelList()
347    {
[8079]348        // Get all files matching the level criteria
[6501]349        Ogre::StringVectorPtr levels = Resource::findResourceNames("*.oxw");
[8079]350
351        // We only want to load as little as possible
352        ClassTreeMask mask;
353        mask.exclude(Class(BaseObject));
354        mask.include(Class(LevelInfo));
355
356        // Iterate over all the found *.oxw files
[8858]357        orxout(internal_info) << "Loading LevelInfos..." << endl;
[8079]358        std::set<std::string> names;
[6501]359        for (Ogre::StringVector::const_iterator it = levels->begin(); it != levels->end(); ++it)
360        {
[8079]361            // TODO: Replace with tag?
[6501]362            if (it->find("old/") != 0)
[3370]363            {
[11071]364                LevelInfoItem* info = nullptr;
[7648]365
[7802]366                // Load the LevelInfo object from the level file.
[7648]367                XMLFile file = XMLFile(*it);
[10624]368                Loader::getInstance().load(&file, mask, false, true);
[8079]369
370                // Find the LevelInfo object we've just loaded (if there was one)
[11071]371                for(LevelInfo* levelInfo : ObjectList<LevelInfo>())
372                    if(levelInfo->getXMLFilename() == *it)
373                        info = levelInfo->copy();
[8079]374
375                // We don't need the loaded stuff anymore
[10624]376                Loader::getInstance().unload(&file);
[8079]377
[11071]378                if(info == nullptr)
[7648]379                {
[8079]380                    // Create a default LevelInfoItem object that merely contains the name
381                    std::string filenameWOExtension = it->substr(0, it->find(".oxw"));
382                    info = new LevelInfoItem(filenameWOExtension, *it);
[7648]383                }
[8079]384
385                // Warn about levels with the same name.
386                if(!names.insert(info->getName()).second)
[8858]387                    orxout(internal_warning) << "Multiple levels (" << info->getXMLFilename() << ") with name '" << info->getName() << "' found!" << endl;
[8079]388
389                // Warn about multiple items so that it gets fixed quickly
390                if(availableLevels_.find(info) != availableLevels_.end())
391                {
[8858]392                    orxout(internal_warning) << "Multiple levels (" << info->getXMLFilename() << ") with same name '" << info->getName() << "' and filename found! Exluding..." << endl;
[8079]393                    // Delete LevelInfoItem to avoid a dangling pointer
394                    delete info;
395                }
396                else
397                    this->availableLevels_.insert(info);
[3370]398            }
[6501]399        }
[3370]400    }
[7648]401
[7802]402    /**
403    @brief
404        Update the list of available Levels.
405    */
[7648]406    void LevelManager::updateAvailableLevelList(void)
407    {
408        //TODO: Implement some kind of update?
409    }
[2072]410}
Note: See TracBrowser for help on using the repository browser.