Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Campaignmenu improved, it's now possible to only show single levels and not all together.

  • Property svn:eol-style set to native
File size: 11.4 KB
Line 
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:
25 *      Damian 'Mozork' Frick
26 *
27 */
28
29/**
30    @file LevelManager.cc
31    @brief Implementation of the LevelManager singleton.
32*/
33
34#include "LevelManager.h"
35
36#include <map>
37
38#include "core/singleton/ScopedSingletonIncludes.h"
39#include "core/commandline/CommandLineIncludes.h"
40#include "core/config/ConfigValueIncludes.h"
41#include "core/CoreIncludes.h"
42#include "core/ClassTreeMask.h"
43#include "core/Loader.h"
44#include "core/Resource.h"
45#include "core/XMLFile.h"
46#include "Level.h"
47#include "PlayerManager.h"
48
49namespace orxonox
50{
51
52    LevelStatus::LevelStatus()
53    {
54        this->won = true;
55    }
56
57    LevelStatus::~LevelStatus()
58    {}
59
60    bool LevelManager::missionactivate(int index)
61    {
62        //check for index level activate...
63        return index-5;
64    }
65
66    void LevelManager::setLevelStatus(int completedLevel)
67    {
68//        allLevelStatus_[completedLevel]=new LevelStatus;
69    }
70
71
72    SetCommandLineArgument(level, "").shortcut("l").information("Default level file (overrides LevelManager::defaultLevelName_ configValue)");
73
74    ManageScopedSingleton(LevelManager, ScopeID::ROOT, false);
75
76    RegisterAbstractClass(LevelManager).inheritsFrom<Configurable>();
77
78    /**
79    @brief
80        Constructor. Registers the object, sets config values and initializes variables.
81    */
82    LevelManager::LevelManager()
83    {
84        RegisterObject(LevelManager);
85        this->setConfigValues();
86
87
88
89        // check override
90        if (!CommandLineParser::getArgument("level")->hasDefaultValue())
91        {
92            ModifyConfigValue(defaultLevelName_, tset, CommandLineParser::getValue("level").get<std::string>());
93        }
94
95        this->compileAvailableLevelList();
96        this->nextIndex_ = 0;
97        this->nextLevel_ = this->availableLevels_.begin();
98
99        allLevelStatus_.reserve(1);
100    }
101
102
103    LevelManager::~LevelManager()
104    {
105        // Delete all the LevelInfoItem objects because the LevelManager created them
106        for (LevelInfoItem* info : availableLevels_)
107            info->destroy();
108    }
109
110    /**
111    @brief
112        Set the config values for this object.
113    */
114    void LevelManager::setConfigValues()
115    {
116        SetConfigValue(defaultLevelName_, "missionOne.oxw")
117            .description("Sets the pre selection of the level in the main menu.");
118        SetConfigValue(lastFinishedCampaignMission_,  "")
119            .description("The last finished mission of a campaign");
120        SetConfigValue(campaignMissions_,  std::vector<std::string>())
121            .description("The list of missions in the campaign");
122    }
123
124    /**
125     * @brief Stores the argument in the corresponding config value.
126     */
127    void LevelManager::setLastFinishedCampaignMission(const std::string& lastFinishedCampaignMission)
128    {
129        ModifyConfigValue(lastFinishedCampaignMission_, set, lastFinishedCampaignMission);
130    }
131
132
133
134    /**
135    @brief
136        Request activity for the input Level.
137        The Level will be added to the list of Levels whose activity is requested. The list is accessed in a FIFO manner.
138        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.
139    @param level
140        A pointer to the Level whose activity is requested.
141    */
142    void LevelManager::requestActivity(Level* level)
143    {
144        assert( std::find(this->levels_.begin(), this->levels_.end(), level)==this->levels_.end() );
145        // If the level is already in list.
146        if( std::find(this->levels_.begin(), this->levels_.end(), level)!=this->levels_.end() )
147            return;
148        // If it isn't insert it at the back.
149        this->levels_.push_back(level);
150        // If it is the only level in the list activate it.
151        if (this->levels_.size() == 1)
152            this->activateNextLevel();
153    }
154
155    /**
156    @brief
157        Release activity for the input Level.
158        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.
159    @param level
160        A pointer to the Level whose activity is to be released.
161    */
162    void LevelManager::releaseActivity(Level* level)
163    {
164        if (this->levels_.size() > 0)
165        {
166            // If the level is the active level in the front of the list.
167            if (this->levels_.front() == level)
168            {
169                // Deactivate it, remove it from the list and activate the next level in line.
170                level->setActive(false);
171                this->levels_.pop_front();
172                this->activateNextLevel();
173            }
174            else // Else just remove it from the list.
175                this->levels_.erase(std::find(this->levels_.begin(), this->levels_.end(), level));
176        }
177    }
178
179    /**
180    @brief
181        Get the currently active Level.
182    @return
183        Returns a pointer to the currently active level or nullptr if there currently are no active Levels.
184    */
185    Level* LevelManager::getActiveLevel()
186    {
187        if (this->levels_.size() > 0)
188            return this->levels_.front();
189        else
190            return nullptr;
191    }
192
193    /**
194    @brief
195        Activate the next Level.
196    */
197    void LevelManager::activateNextLevel()
198    {
199        if (this->levels_.size() > 0)
200        {
201            // Activate the level that is the first in the list of levels whose activity has been requested.
202            this->levels_.front()->setActive(true);
203            // Make every player enter the newly activated level.
204            for (const auto& mapEntry : PlayerManager::getInstance().getClients())
205                this->levels_.front()->playerEntered(mapEntry.second);
206        }
207    }
208
209    /**
210    @brief
211        Set the default Level.
212    @param levelName
213        The filename of the default Level.
214    */
215    void LevelManager::setDefaultLevel(const std::string& levelName)
216    {
217        ModifyConfigValue(defaultLevelName_, set, levelName);
218    }
219
220    /**
221    @brief
222        Get the number of available Levels.
223        Also updates the list of available Levels.
224    @return
225        Returns the number of available Levels.
226    */
227    unsigned int LevelManager::getNumberOfLevels()
228    {
229        this->updateAvailableLevelList();
230
231        return this->availableLevels_.size();
232    }
233
234    /**
235    @brief
236        Get the LevelInfoItem at the given index in the list of available Levels.
237        The LevelInfoItems are sorted in alphabetical order accoridng to the name of the Level.
238        This method is most efficiently called with consecutive indices (or at least ascending indices).
239    @param index
240        The index of the item that should be returned.
241    @return
242        Returns a pointer to the LevelInfoItem at the given index.
243    */
244    LevelInfoItem* LevelManager::getAvailableLevelListItem(unsigned int index)
245    {
246        if(index >= this->availableLevels_.size())
247            return nullptr;
248
249        // If this index directly follows the last we can optimize a lot.
250        if(index == this->nextIndex_)
251        {
252            this->nextIndex_++;
253            std::set<LevelInfoItem*, LevelInfoCompare>::iterator it = this->nextLevel_;
254            this->nextLevel_++;
255            return *it;
256        }
257        else
258        {
259            // If this index is bigger than the last, we can optimize a little.
260            if(index < this->nextIndex_)
261            {
262                this->nextIndex_ = 0;
263                this->nextLevel_ = this->availableLevels_.begin();
264            }
265
266            while(this->nextIndex_ != index)
267            {
268                this->nextIndex_++;
269                this->nextLevel_++;
270            }
271            this->nextIndex_++;
272            std::set<LevelInfoItem*, LevelInfoCompare>::iterator it = this->nextLevel_;
273            this->nextLevel_++;
274            return *it;
275        }
276    }
277
278    /**
279    @brief
280        Compile the list of available Levels.
281        Iterates over all *.oxw files, loads the LevelInfo objects in them and from that it creates the LevelInfoItems which are inserted in a list.
282    */
283    void LevelManager::compileAvailableLevelList()
284    {
285        // Get all files matching the level criteria
286        Ogre::StringVectorPtr levels = Resource::findResourceNames("*.oxw");
287
288        // We only want to load as little as possible
289        ClassTreeMask mask;
290        mask.exclude(Class(BaseObject));
291        mask.include(Class(LevelInfo));
292
293        // Iterate over all the found *.oxw files
294        orxout(internal_info) << "Loading LevelInfos..." << endl;
295        std::set<std::string> names;
296        for (Ogre::StringVector::const_iterator it = levels->begin(); it != levels->end(); ++it)
297        {
298            // TODO: Replace with tag?
299            if (it->find("old/") != 0)
300            {
301                LevelInfoItem* info = nullptr;
302
303                // Load the LevelInfo object from the level file.
304                XMLFile file = XMLFile(*it);
305                Loader::getInstance().load(&file, mask, false, true);
306
307                // Find the LevelInfo object we've just loaded (if there was one)
308                for(LevelInfo* levelInfo : ObjectList<LevelInfo>())
309                    if(levelInfo->getXMLFilename() == *it)
310                        info = levelInfo->copy();
311
312                // We don't need the loaded stuff anymore
313                Loader::getInstance().unload(&file);
314
315                if(info == nullptr)
316                {
317                    // Create a default LevelInfoItem object that merely contains the name
318                    std::string filenameWOExtension = it->substr(0, it->find(".oxw"));
319                    info = new LevelInfoItem(filenameWOExtension, *it);
320                }
321
322                // Warn about levels with the same name.
323                if(!names.insert(info->getName()).second)
324                    orxout(internal_warning) << "Multiple levels (" << info->getXMLFilename() << ") with name '" << info->getName() << "' found!" << endl;
325
326                // Warn about multiple items so that it gets fixed quickly
327                if(availableLevels_.find(info) != availableLevels_.end())
328                {
329                    orxout(internal_warning) << "Multiple levels (" << info->getXMLFilename() << ") with same name '" << info->getName() << "' and filename found! Exluding..." << endl;
330                    // Delete LevelInfoItem to avoid a dangling pointer
331                    delete info;
332                }
333                else
334                    this->availableLevels_.insert(info);
335            }
336        }
337    }
338
339    /**
340    @brief
341        Update the list of available Levels.
342    */
343    void LevelManager::updateAvailableLevelList(void)
344    {
345        //TODO: Implement some kind of update?
346    }
347}
Note: See TracBrowser for help on using the repository browser.