Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/gametypes/Gametype.cc @ 10426

Last change on this file since 10426 was 10281, checked in by landauf, 10 years ago

added command 'reloadLevel' (by default on F5) which reloads the level while the player's camera remains at the same position

  • Property svn:eol-style set to native
File size: 18.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 *      ...
26 *
27 */
28
29#include "Gametype.h"
30
31#include "util/Math.h"
32#include "core/Core.h"
33#include "core/CoreIncludes.h"
34#include "core/config/ConfigValueIncludes.h"
35#include "core/GameMode.h"
36#include "core/command/ConsoleCommand.h"
37#include "gamestates/GSLevel.h"
38
39#include "infos/PlayerInfo.h"
40#include "infos/Bot.h"
41#include "graphics/Camera.h"
42#include "worldentities/ControllableEntity.h"
43#include "worldentities/SpawnPoint.h"
44#include "worldentities/pawns/Spectator.h"
45#include "worldentities/pawns/Pawn.h"
46#include "overlays/OverlayGroup.h"
47#include "Scene.h"
48
49namespace orxonox
50{
51    RegisterUnloadableClass(Gametype);
52
53    Gametype::Gametype(Context* context) : BaseObject(context)
54    {
55        RegisterObject(Gametype);
56
57        this->gtinfo_ = new GametypeInfo(context);
58
59        this->setGametype(SmartPtr<Gametype>(this, false));
60
61        this->defaultControllableEntity_ = Class(Spectator);
62
63        this->bAutoStart_ = false;
64        this->bForceSpawn_ = false;
65        this->bAutoEnd_ = true;
66        this->numberOfBots_ = 0;
67
68        this->timeLimit_ = 0;
69        this->time_ = 0;
70        this->timerIsActive_ = false;
71
72        this->initialStartCountdown_ = 3;
73
74        this->setConfigValues();
75
76        // load the corresponding score board
77        if (GameMode::showsGraphics() && !this->scoreboardTemplate_.empty())
78        {
79            this->scoreboard_ = new OverlayGroup(context);
80            this->scoreboard_->addTemplate(this->scoreboardTemplate_);
81            this->scoreboard_->setGametype(this);
82        }
83        else
84            this->scoreboard_ = 0;
85
86        /* HACK HACK HACK */
87        this->dedicatedAddBots_ = createConsoleCommand( "dedicatedAddBots", createExecutor( createFunctor(&Gametype::addBots, this) ) );
88        this->dedicatedKillBots_ = createConsoleCommand( "dedicatedKillBots", createExecutor( createFunctor(&Gametype::killBots, this) ) );
89        /* HACK HACK HACK */
90    }
91
92    Gametype::~Gametype()
93    {
94        if (this->isInitialized())
95        {
96            this->gtinfo_->destroy();
97            if( this->dedicatedAddBots_ )
98                delete this->dedicatedAddBots_;
99            if( this->dedicatedKillBots_ )
100                delete this->dedicatedKillBots_;
101        }
102    }
103
104    void Gametype::setConfigValues()
105    {
106        SetConfigValue(initialStartCountdown_, 3.0f);
107        SetConfigValue(bAutoStart_, false);
108        SetConfigValue(bForceSpawn_, false);
109        SetConfigValue(bAutoEnd_, true);
110        SetConfigValue(numberOfBots_, 0);
111        SetConfigValue(scoreboardTemplate_, "defaultScoreboard");
112    }
113
114    void Gametype::tick(float dt)
115    {
116        SUPER(Gametype, tick, dt);
117
118        //count timer
119        if (timerIsActive_)
120        {
121            if (this->timeLimit_ == 0)
122                this->time_ += dt;
123            else
124                this->time_ -= dt;
125        }
126
127        if (this->gtinfo_->isStartCountdownRunning() && !this->gtinfo_->hasStarted())
128            this->gtinfo_->countdownStartCountdown(dt);
129
130        if (!this->gtinfo_->hasStarted())
131        {
132            for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
133            {
134                // Inform the GametypeInfo that the player is ready to spawn.
135                if(it->first->isHumanPlayer() && it->first->isReadyToSpawn())
136                    this->gtinfo_->playerReadyToSpawn(it->first);
137            }
138
139            this->checkStart();
140        }
141        else if (!this->gtinfo_->hasEnded())
142            this->spawnDeadPlayersIfRequested();
143
144        this->assignDefaultPawnsIfNeeded();
145    }
146
147    void Gametype::start()
148    {
149        this->addBots(this->numberOfBots_);
150        this->gtinfo_->start();
151        this->spawnPlayersIfRequested();
152    }
153
154    void Gametype::end()
155    {
156        this->gtinfo_->end();
157        if (this->bAutoEnd_)
158        {
159            this->showMenuTimer_.setTimer(3.0f, true, createExecutor(createFunctor(&Gametype::showMenu, this)));
160        }
161
162        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
163        {
164            if (it->first->getControllableEntity())
165            {
166                ControllableEntity* oldentity = it->first->getControllableEntity();
167
168                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(oldentity->getContext());
169                if (oldentity->getCamera())
170                {
171                    entity->setPosition(oldentity->getCamera()->getWorldPosition());
172                    entity->setOrientation(oldentity->getCamera()->getWorldOrientation());
173                }
174                else
175                {
176                    entity->setPosition(oldentity->getWorldPosition());
177                    entity->setOrientation(oldentity->getWorldOrientation());
178                }
179                it->first->startControl(entity);
180            }
181            else
182                this->spawnPlayerAsDefaultPawn(it->first);
183        }
184    }
185
186    void Gametype::playerEntered(PlayerInfo* player)
187    {
188        this->players_[player].state_ = PlayerState::Joined;
189        this->gtinfo_->playerEntered(player);
190    }
191
192    bool Gametype::playerLeft(PlayerInfo* player)
193    {
194        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
195        if (it != this->players_.end())
196        {
197            this->players_.erase(it);
198            return true;
199        }
200        return false;
201    }
202
203    void Gametype::playerSwitched(PlayerInfo* player, Gametype* newgametype)
204    {
205    }
206
207    void Gametype::playerSwitchedBack(PlayerInfo* player, Gametype* oldgametype)
208    {
209    }
210
211    bool Gametype::playerChangedName(PlayerInfo* player)
212    {
213        if (this->players_.find(player) != this->players_.end())
214        {
215            if (player->getName() != player->getOldName())
216            {
217                return true;
218            }
219        }
220        return false;
221    }
222
223    void Gametype::pawnPreSpawn(Pawn* pawn)
224    {
225    }
226
227    void Gametype::pawnPostSpawn(Pawn* pawn)
228    {
229    }
230
231    void Gametype::playerPreSpawn(PlayerInfo* player)
232    {
233    }
234
235    void Gametype::playerPostSpawn(PlayerInfo* player)
236    {
237    }
238
239    void Gametype::playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn)
240    {
241    }
242
243    void Gametype::playerStopsControllingPawn(PlayerInfo* player, Pawn* pawn)
244    {
245    }
246
247    bool Gametype::allowPawnHit(Pawn* victim, Pawn* originator)
248    {
249        return true;
250    }
251
252    bool Gametype::allowPawnDamage(Pawn* victim, Pawn* originator)
253    {
254        return true;
255    }
256
257    bool Gametype::allowPawnDeath(Pawn* victim, Pawn* originator)
258    {
259        return true;
260    }
261
262    void Gametype::pawnKilled(Pawn* victim, Pawn* killer)
263    {
264        if (victim && victim->getPlayer())
265        {
266            std::map<PlayerInfo*, Player>::iterator it = this->players_.find(victim->getPlayer());
267            if (it != this->players_.end())
268            {
269                it->second.state_ = PlayerState::Dead;
270                it->second.killed_++;
271
272                // Reward killer
273                if (killer && killer->getPlayer())
274                {
275                    std::map<PlayerInfo*, Player>::iterator it = this->players_.find(killer->getPlayer());
276                    if (it != this->players_.end())
277                    {
278                        it->second.frags_++;
279
280                        if (killer->getPlayer()->getClientID() != NETWORK_PEER_ID_UNKNOWN)
281                            this->gtinfo_->sendKillMessage("You killed " + victim->getPlayer()->getName(), killer->getPlayer()->getClientID());
282                        if (victim->getPlayer()->getClientID() != NETWORK_PEER_ID_UNKNOWN)
283                            this->gtinfo_->sendDeathMessage("You were killed by " + killer->getPlayer()->getName(), victim->getPlayer()->getClientID());
284                    }
285                }
286
287                if(victim->getPlayer()->isHumanPlayer())
288                    this->gtinfo_->pawnKilled(victim->getPlayer());
289
290                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(victim->getContext());
291                if (victim->getCamera())
292                {
293                    entity->setPosition(victim->getCamera()->getWorldPosition());
294                    entity->setOrientation(victim->getCamera()->getWorldOrientation());
295                }
296                else
297                {
298                    entity->setPosition(victim->getWorldPosition());
299                    entity->setOrientation(victim->getWorldOrientation());
300                }
301                it->first->startControl(entity);
302            }
303            else
304                orxout(internal_warning) << "Killed Pawn was not in the playerlist" << endl;
305        }
306    }
307
308    void Gametype::playerScored(PlayerInfo* player, int score)
309    {
310        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
311        if (it != this->players_.end())
312            it->second.frags_ += score;
313    }
314
315    int Gametype::getScore(PlayerInfo* player) const
316    {
317        std::map<PlayerInfo*, Player>::const_iterator it = this->players_.find(player);
318        if (it != this->players_.end())
319            return it->second.frags_;
320        else
321            return 0;
322    }
323
324    SpawnPoint* Gametype::getBestSpawnPoint(PlayerInfo* player) const
325    {
326        // If there is at least one SpawnPoint.
327        if (this->spawnpoints_.size() > 0)
328        {
329            // Fallback spawn point if there is no active one, choose a random one.
330            SpawnPoint* fallbackSpawnPoint = NULL;
331            unsigned int randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(this->spawnpoints_.size())));
332            unsigned int index = 0;
333            std::vector<SpawnPoint*> activeSpawnPoints;
334            for (std::set<SpawnPoint*>::const_iterator it = this->spawnpoints_.begin(); it != this->spawnpoints_.end(); ++it)
335            {
336                if (index == randomspawn)
337                    fallbackSpawnPoint = (*it);
338
339                if (*it != NULL && (*it)->isActive())
340                    activeSpawnPoints.push_back(*it);
341
342                ++index;
343            }
344
345            if(activeSpawnPoints.size() > 0)
346            {
347                randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(activeSpawnPoints.size())));
348                return activeSpawnPoints[randomspawn];
349            }
350
351            orxout(internal_warning) << "Fallback SpawnPoint was used because there were no active SpawnPoints." << endl;
352            return fallbackSpawnPoint;
353        }
354        return 0;
355    }
356
357    void Gametype::assignDefaultPawnsIfNeeded()
358    {
359        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
360        {
361            if (!it->first->getControllableEntity())
362            {
363                it->second.state_ = PlayerState::Dead;
364
365                if (!it->first->isReadyToSpawn() || !this->gtinfo_->hasStarted())
366                {
367                    this->spawnPlayerAsDefaultPawn(it->first);
368                    it->second.state_ = PlayerState::Dead;
369                }
370            }
371        }
372    }
373
374    void Gametype::checkStart()
375    {
376        if (!this->gtinfo_->hasStarted())
377        {
378            if (this->gtinfo_->isStartCountdownRunning())
379            {
380                if (this->gtinfo_->getStartCountdown() <= 0.0f)
381                {
382                    this->gtinfo_->stopStartCountdown();
383                    this->gtinfo_->setStartCountdown(0.0f);
384                    this->start();
385                }
386            }
387            else if (this->players_.size() > 0)
388            {
389                if (this->bAutoStart_)
390                {
391                    this->start();
392                }
393                else
394                {
395                    bool allplayersready = true;
396                    bool hashumanplayers = false;
397                    for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
398                    {
399                        if (!it->first->isReadyToSpawn())
400                            allplayersready = false;
401                        if (it->first->isHumanPlayer())
402                            hashumanplayers = true;
403                    }
404
405                    if (allplayersready && hashumanplayers)
406                    {
407                        // If in developer's mode, there is no start countdown.
408                        if(Core::getInstance().inDevMode())
409                            this->start();
410                        else
411                        {
412                            this->gtinfo_->setStartCountdown(this->initialStartCountdown_);
413                            this->gtinfo_->startStartCountdown();
414                        }
415                    }
416                }
417            }
418        }
419    }
420
421    void Gametype::spawnPlayersIfRequested()
422    {
423        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
424        {
425            if (it->first->isReadyToSpawn() || this->bForceSpawn_)
426                this->spawnPlayer(it->first);
427        }
428    }
429
430    void Gametype::spawnDeadPlayersIfRequested()
431    {
432        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
433            if (it->second.state_ == PlayerState::Dead)
434                if (it->first->isReadyToSpawn() || this->bForceSpawn_)
435                    this->spawnPlayer(it->first);
436    }
437
438    void Gametype::spawnPlayer(PlayerInfo* player)
439    {
440        SpawnPoint* spawnpoint = this->getBestSpawnPoint(player);
441        if (spawnpoint)
442        {
443            this->playerPreSpawn(player);
444            player->startControl(spawnpoint->spawn());
445            this->players_[player].state_ = PlayerState::Alive;
446
447            if(player->isHumanPlayer())
448                this->gtinfo_->playerSpawned(player);
449
450            this->playerPostSpawn(player);
451        }
452        else
453        {
454            orxout(user_error) << "No SpawnPoints in current Gametype" << endl;
455            abort();
456        }
457    }
458
459    void Gametype::spawnPlayerAsDefaultPawn(PlayerInfo* player)
460    {
461        SpawnPoint* spawn = this->getBestSpawnPoint(player);
462        if (spawn)
463        {
464            // force spawn at spawnpoint with default pawn
465            ControllableEntity* entity = this->defaultControllableEntity_.fabricate(spawn->getContext());
466            spawn->spawn(entity);
467            player->startControl(entity);
468        }
469        else
470        {
471            orxout(user_error) << "No SpawnPoints in current Gametype" << endl;
472            abort();
473        }
474    }
475
476    void Gametype::addBots(unsigned int amount)
477    {
478        for (unsigned int i = 0; i < amount; ++i)
479            this->botclass_.fabricate(this->getContext());
480    }
481
482    void Gametype::killBots(unsigned int amount)
483    {
484        unsigned int i = 0;
485        for (ObjectList<Bot>::iterator it = ObjectList<Bot>::begin(); (it != ObjectList<Bot>::end()) && ((amount == 0) || (i < amount)); )
486        {
487            if (it->getGametype() == this)
488            {
489                (it++)->destroy();
490                ++i;
491            }
492            else
493                ++it;
494        }
495    }
496
497    void Gametype::addTime(float t)
498    {
499        if (this->timeLimit_ == 0)
500          this->time_ -= t;
501        else
502          this->time_ += t;
503    }
504
505    void Gametype::removeTime(float t)
506    {
507        if (this->timeLimit_ == 0)
508          this->time_ += t;
509        else
510          this->time_ -= t;
511    }
512
513    void Gametype::resetTimer()
514    {
515        this->resetTimer(timeLimit_);
516    }
517
518    void Gametype::resetTimer(float t)
519    {
520        this->timeLimit_ = t;
521        this->time_ = t;
522    }
523
524    void Gametype::showMenu()
525    {
526        GSLevel::startMainMenu();
527    }
528
529    GSLevelMementoState* Gametype::exportMementoState()
530    {
531        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
532        {
533            if (it->first->isHumanPlayer() && it->first->getControllableEntity() && it->first->getControllableEntity()->getCamera())
534            {
535                Camera* camera = it->first->getControllableEntity()->getCamera();
536
537                GametypeMementoState* state = new GametypeMementoState();
538                state->cameraPosition_ = camera->getWorldPosition();
539                state->cameraOrientation_ = camera->getWorldOrientation();
540                state->sceneName_ = camera->getScene()->getName();
541                return state;
542            }
543        }
544
545        return NULL;
546    }
547
548    void Gametype::importMementoState(const std::vector<GSLevelMementoState*>& states)
549    {
550        // find correct memento state
551        GametypeMementoState* state = NULL;
552        for (size_t i = 0; i < states.size(); ++i)
553        {
554            state = dynamic_cast<GametypeMementoState*>(states[i]);
555            if (state)
556                break;
557        }
558
559        if (!state)
560            return;
561
562        // find correct scene
563        Scene* scene = NULL;
564        for (ObjectList<Scene>::iterator it = ObjectList<Scene>::begin(); it != ObjectList<Scene>::end(); ++it)
565        {
566            if (it->getName() == state->sceneName_)
567            {
568                scene = *it;
569                break;
570            }
571        }
572
573        if (!scene)
574        {
575            orxout(internal_warning) << "Could not find scene with name " << state->sceneName_ << endl;
576            return;
577        }
578
579        // find correct player and assign default entity with original position & orientation
580        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
581        {
582            if (it->first->isHumanPlayer())
583            {
584                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(scene->getContext());
585                entity->setPosition(state->cameraPosition_);
586                entity->setOrientation(state->cameraOrientation_);
587                it->first->startControl(entity);
588                break;
589            }
590        }
591    }
592}
Note: See TracBrowser for help on using the repository browser.