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
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
49
50namespace orxonox
51{
52
53//Mission endmission true
54    //check if index level is activated...
55    int LevelManager::missionactivate(int index)
56    {
57        updateAllLevelStatus();
58        int activated = allLevelStatus_[index].activated;
59        return activated;
60    }
61
62    void LevelManager::updatewon(int lastwon)
63    {
64        allLevelStatus_[lastwon].won=true;
65
66    }
67
68    void LevelManager::updateAllLevelStatus()
69    {
70        for(unsigned int i =0;i<allLevelStatus_.size();i++)
71        {
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        }
82    }
83
84    //updates the won variable of the corresponding LevelStatus in allLevelStatus_
85    void LevelManager::setLevelStatus(const std::string& LevelWon)
86    {
87        ModifyConfigValue(lastWonMission_, set, LevelWon); 
88    }
89
90
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;
97        allLevelStatus_.assign (campaignMissions_.size(),level);
98        allLevelStatus_[0].activated=1;
99        //allLevelStatus_[0].won=true;
100
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);
111        allLevelStatus_[1].nextLevels.push_back(2);
112        allLevelStatus_[1].nextLevels.push_back(1);
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);
117
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);
125
126
127
128    }
129
130
131
132    SetCommandLineArgument(level, "").shortcut("l").information("Default level file (overrides LevelManager::defaultLevelName_ configValue)");
133
134    ManageScopedSingleton(LevelManager, ScopeID::ROOT, false);
135
136    RegisterAbstractClass(LevelManager).inheritsFrom<Configurable>();
137
138    /**
139    @brief
140        Constructor. Registers the object, sets config values and initializes variables.
141    */
142    LevelManager::LevelManager()
143    {
144        RegisterObject(LevelManager);
145        this->setConfigValues();
146
147
148
149        // check override
150        if (!CommandLineParser::getArgument("level")->hasDefaultValue())
151        {
152            ModifyConfigValue(defaultLevelName_, tset, CommandLineParser::getValue("level").get<std::string>());
153        }
154
155        this->compileAvailableLevelList();
156        this->nextIndex_ = 0;
157        this->nextLevel_ = this->availableLevels_.begin();
158
159        buildallLevelStatus();
160    }
161
162
163    LevelManager::~LevelManager()
164    {
165        // Delete all the LevelInfoItem objects because the LevelManager created them
166        for (LevelInfoItem* info : availableLevels_)
167            info->destroy();
168    }
169
170    /**
171    @brief
172        Set the config values for this object.
173    */
174    void LevelManager::setConfigValues()
175    {
176        SetConfigValue(defaultLevelName_, "missionOne.oxw")
177            .description("Sets the pre selection of the level in the main menu.");
178        SetConfigValue(lastWonMission_,  "")
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");
182        SetConfigValue(test_,  std::vector<int>())
183            .description("The list of missions and their statuses");
184           
185    }
186
187    /**
188     * @brief Stores the argument in the corresponding config value.
189     */
190/*    void LevelManager::setLastFinishedCampaignMission(const std::string& lastFinishedCampaignMission)
191    {
192        ModifyConfigValue(lastWonMission_, set, lastFinishedCampaignMission);
193    }
194*/
195
196
197    /**
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    */
205    void LevelManager::requestActivity(Level* level)
206    {
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)
215            this->activateNextLevel();
216    }
217
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    */
225    void LevelManager::releaseActivity(Level* level)
226    {
227        if (this->levels_.size() > 0)
228        {
229            // If the level is the active level in the front of the list.
230            if (this->levels_.front() == level)
231            {
232                // Deactivate it, remove it from the list and activate the next level in line.
233                level->setActive(false);
234                this->levels_.pop_front();
235                this->activateNextLevel();
236            }
237            else // Else just remove it from the list.
238                this->levels_.erase(std::find(this->levels_.begin(), this->levels_.end(), level));
239        }
240    }
241
242    /**
243    @brief
244        Get the currently active Level.
245    @return
246        Returns a pointer to the currently active level or nullptr if there currently are no active Levels.
247    */
248    Level* LevelManager::getActiveLevel()
249    {
250        if (this->levels_.size() > 0)
251            return this->levels_.front();
252        else
253            return nullptr;
254    }
255
256    /**
257    @brief
258        Activate the next Level.
259    */
260    void LevelManager::activateNextLevel()
261    {
262        if (this->levels_.size() > 0)
263        {
264            // Activate the level that is the first in the list of levels whose activity has been requested.
265            this->levels_.front()->setActive(true);
266            // Make every player enter the newly activated level.
267            for (const auto& mapEntry : PlayerManager::getInstance().getClients())
268                this->levels_.front()->playerEntered(mapEntry.second);
269        }
270    }
271
272    /**
273    @brief
274        Set the default Level.
275    @param levelName
276        The filename of the default Level.
277    */
278    void LevelManager::setDefaultLevel(const std::string& levelName)
279    {
280        ModifyConfigValue(defaultLevelName_, set, levelName);
281    }
282
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    */
290    unsigned int LevelManager::getNumberOfLevels()
291    {
292        this->updateAvailableLevelList();
293
294        return this->availableLevels_.size();
295    }
296
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).
302    @param index
303        The index of the item that should be returned.
304    @return
305        Returns a pointer to the LevelInfoItem at the given index.
306    */
307    LevelInfoItem* LevelManager::getAvailableLevelListItem(unsigned int index)
308    {
309        if(index >= this->availableLevels_.size())
310            return nullptr;
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        }
320        else
321        {
322            // If this index is bigger than the last, we can optimize a little.
323            if(index < this->nextIndex_)
324            {
325                this->nextIndex_ = 0;
326                this->nextLevel_ = this->availableLevels_.begin();
327            }
328
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;
338        }
339    }
340
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    */
346    void LevelManager::compileAvailableLevelList()
347    {
348        // Get all files matching the level criteria
349        Ogre::StringVectorPtr levels = Resource::findResourceNames("*.oxw");
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
357        orxout(internal_info) << "Loading LevelInfos..." << endl;
358        std::set<std::string> names;
359        for (Ogre::StringVector::const_iterator it = levels->begin(); it != levels->end(); ++it)
360        {
361            // TODO: Replace with tag?
362            if (it->find("old/") != 0)
363            {
364                LevelInfoItem* info = nullptr;
365
366                // Load the LevelInfo object from the level file.
367                XMLFile file = XMLFile(*it);
368                Loader::getInstance().load(&file, mask, false, true);
369
370                // Find the LevelInfo object we've just loaded (if there was one)
371                for(LevelInfo* levelInfo : ObjectList<LevelInfo>())
372                    if(levelInfo->getXMLFilename() == *it)
373                        info = levelInfo->copy();
374
375                // We don't need the loaded stuff anymore
376                Loader::getInstance().unload(&file);
377
378                if(info == nullptr)
379                {
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);
383                }
384
385                // Warn about levels with the same name.
386                if(!names.insert(info->getName()).second)
387                    orxout(internal_warning) << "Multiple levels (" << info->getXMLFilename() << ") with name '" << info->getName() << "' found!" << endl;
388
389                // Warn about multiple items so that it gets fixed quickly
390                if(availableLevels_.find(info) != availableLevels_.end())
391                {
392                    orxout(internal_warning) << "Multiple levels (" << info->getXMLFilename() << ") with same name '" << info->getName() << "' and filename found! Exluding..." << endl;
393                    // Delete LevelInfoItem to avoid a dangling pointer
394                    delete info;
395                }
396                else
397                    this->availableLevels_.insert(info);
398            }
399        }
400    }
401
402    /**
403    @brief
404        Update the list of available Levels.
405    */
406    void LevelManager::updateAvailableLevelList(void)
407    {
408        //TODO: Implement some kind of update?
409    }
410}
Note: See TracBrowser for help on using the repository browser.