1 // Description:
2 // Stage manager controls movement from levelpack to levelpack and
3 // level to level.
4 //
5 // Copyright (C) 2001 Frank Becker
6 //
7 // This program is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU General Public License as published by the Free Software
9 // Foundation; either version 2 of the License, or (at your option) any later
10 // version.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
15 //
16 #include <Trace.hpp>
17 #include <Constants.hpp>
18 #include <GameState.hpp>
19 #include <StageManager.hpp>
20 #include <EnemyFactory.hpp>
21 #include <Skill.hpp>
22 #include <XMLHelper.hpp>
23 #include <Config.hpp>
24 #include <Hero.hpp>
25
26 #include <Random.hpp>
27 #include <ParticleInfo.hpp>
28 #include <Particles.hpp>
29 #include <ParticleGroup.hpp>
30 #include <ParticleGroupManager.hpp>
31
init(void)32 bool StageManager::init( void)
33 {
34 return findLevelPacks();
35 }
36
reset(void)37 void StageManager::reset( void)
38 {
39 //catch used skill changes via runtime config
40 SkillS::instance()->updateSkill();
41
42 _levelPackIterator = _levelPackList.begin();
43 loadNextLevelPack();
44 activateLevel();
45 }
46
update(void)47 void StageManager::update( void)
48 {
49 static ParticleGroup *bonus =
50 ParticleGroupManagerS::instance()->getParticleGroup( BONUS_GROUP);
51
52 //no armor piercing needed for rookie
53 if( (GameState::skill != Skill::eRookie) &&
54 (HeroS::instance()->getArmorPierce() <= 1.0f))
55 {
56 if( Random::rangef0_1() < 0.001f)
57 {
58 LOG_INFO << "ArmorPierce" << endl;
59 float posX = (Random::rangef0_1()-0.5f) * 60.0f;
60 bonus->newParticle( "ArmorPierce", posX, 49.0f, -100.0f);
61 }
62 }
63
64 if( GameState::numObjects == 0)
65 {
66 if( _delayEndOfLevel-- > 0) return;
67
68 _activeLevelIndex++;
69 if( _activeLevelIndex >= _levelList.size())
70 {
71 loadNextLevelPack();
72 }
73 else
74 {
75 _activeLevel = _levelList[ _activeLevelIndex];
76 }
77 activateLevel();
78 }
79 }
80
findLevelPacks(void)81 bool StageManager::findLevelPacks( void)
82 {
83 list<string> rList;
84 ResourceManagerS::instance()->getResourceList( rList);
85
86 list<string>::iterator i;
87 for( i=rList.begin(); i!=rList.end(); i++)
88 {
89 string resourceName = *i;
90
91 string::size_type end = resourceName.length()-8; // strlen("Pack.xml")
92 string::size_type find = resourceName.find("Pack.xml");
93 if( (find!=string::npos) && (find==end))
94 {
95 LOG_INFO << "Adding LevelPack [" << resourceName << "]" << endl;
96 _levelPackList.insert( _levelPackList.end(), resourceName);
97 }
98 }
99
100
101 _levelPackIterator = _levelPackList.begin();
102
103 bool foundSome = _levelPackIterator != _levelPackList.end();
104 if( !foundSome)
105 {
106 LOG_WARNING << "No levelpacks found in resource file!" << endl;
107 string defaultLevelPack = "levelpacks/CritterPack.xml";
108 _levelPackList.insert( _levelPackList.end(), defaultLevelPack);
109 }
110
111 return true;
112 }
113
loadNextLevelPack(void)114 bool StageManager::loadNextLevelPack( void)
115 {
116 XTRACE();
117
118 if( _levelPackIterator == _levelPackList.end())
119 {
120 _levelPackIterator = _levelPackList.begin();
121 //when we wrap around, increment skill
122 SkillS::instance()->incrementSkill();
123 }
124
125 delete _activeLevelPack;
126
127 string levelPackName = *_levelPackIterator;
128 _activeLevelPack = XMLHelper::load( levelPackName);
129
130 if( !_activeLevelPack)
131 {
132 _activeLevel = 0;
133 return false;
134 }
135
136 TiXmlNode *levelPack = _activeLevelPack->FirstChild("LevelPack");
137
138 _activeLevel = levelPack->ToElement()->FirstChild();
139 _levelList.clear();
140 while( _activeLevel)
141 {
142 _levelList.push_back(_activeLevel);
143 _activeLevel = _activeLevel->NextSibling();
144 }
145
146 bool randomLevels = false;
147 ConfigS::instance()->getBoolean( "randomLevels", randomLevels);
148 if( randomLevels)
149 {
150 int levelCount = _levelList.size();
151 for( int i=0; i<levelCount*10; i++)
152 {
153 int r1 = Random::integer(levelCount);
154 int r2 = Random::integer(levelCount);
155 std::swap( _levelList[r1], _levelList[r2]);
156 }
157 }
158 _activeLevelIndex = 0;
159 _activeLevel = _levelList[_activeLevelIndex];
160
161 //advance to next level pack
162 _levelPackIterator++;
163
164 if( !_activeLevelPack)
165 {
166 LOG_ERROR << "No level pack found!" << endl;
167 return false;
168 }
169
170 return true;
171 }
172
activateLevel(void)173 bool StageManager::activateLevel( void)
174 {
175 XTRACE();
176
177 if( !_activeLevel)
178 {
179 return false;
180 }
181
182 GameState::stopwatch.pause();
183
184 TiXmlElement* levelNode = _activeLevel->ToElement();
185 _activeLevelName = levelNode->Attribute("Name");
186 LOG_INFO << "Level '" << _activeLevelName
187 << "' by " << levelNode->Attribute("Author") << endl;
188
189 static ParticleGroup *effects =
190 ParticleGroupManagerS::instance()->getParticleGroup( EFFECTS_GROUP2);
191 ParticleInfo pi;
192 pi.position.x = 0.0;
193 pi.position.y = 0.0;
194 pi.position.z =-50.0;
195 pi.text = _activeLevelName;
196
197 pi.color.x = 1.0;
198 pi.color.y = 1.0;
199 pi.color.z = 1.0;
200
201 pi.extra.y = 0.1f;
202 pi.extra.z = 0.1f;
203
204 effects->newParticle( "StatusMessage", pi);
205
206 GameState::numObjects = 0;
207 _levelStartTime = GameState::stopwatch.getTime();
208 _delayEndOfLevel = 60; //2 sec
209
210 TiXmlNode *enemyNode = _activeLevel->FirstChild();
211 while( enemyNode)
212 {
213 EnemyFactory::createEnemy( enemyNode);
214 enemyNode = enemyNode->NextSibling();
215 }
216
217 GameState::startOfStep = Timer::getTime(); //get fresh start for other logic
218
219 GameState::stopwatch.start();
220 LOG_INFO << "Starting game timer\n";
221
222 return true;
223 }
224