Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

The Campaign menu now works. The levels are structured in a tree. If one goes the left branch, the right one can't be taken anymore. The last challenge is to save the progress in the config variables. to set does work, but not to modify those variables.

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