Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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