Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10448 was 10281, checked in by landauf, 9 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
RevLine 
[2072]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
[3196]31#include "util/Math.h"
[8079]32#include "core/Core.h"
[2072]33#include "core/CoreIncludes.h"
[9667]34#include "core/config/ConfigValueIncludes.h"
[2896]35#include "core/GameMode.h"
[7284]36#include "core/command/ConsoleCommand.h"
[9977]37#include "gamestates/GSLevel.h"
[3196]38
[5735]39#include "infos/PlayerInfo.h"
40#include "infos/Bot.h"
[5737]41#include "graphics/Camera.h"
[5735]42#include "worldentities/ControllableEntity.h"
43#include "worldentities/SpawnPoint.h"
44#include "worldentities/pawns/Spectator.h"
45#include "worldentities/pawns/Pawn.h"
[3196]46#include "overlays/OverlayGroup.h"
[10281]47#include "Scene.h"
[2072]48
49namespace orxonox
50{
[9667]51    RegisterUnloadableClass(Gametype);
[2072]52
[9667]53    Gametype::Gametype(Context* context) : BaseObject(context)
[2072]54    {
55        RegisterObject(Gametype);
[6417]56
[9667]57        this->gtinfo_ = new GametypeInfo(context);
[2072]58
[5929]59        this->setGametype(SmartPtr<Gametype>(this, false));
[2662]60
[2072]61        this->defaultControllableEntity_ = Class(Spectator);
62
63        this->bAutoStart_ = false;
64        this->bForceSpawn_ = false;
[9977]65        this->bAutoEnd_ = true;
[2662]66        this->numberOfBots_ = 0;
[2072]67
[3033]68        this->timeLimit_ = 0;
69        this->time_ = 0;
70        this->timerIsActive_ = false;
71
[2072]72        this->initialStartCountdown_ = 3;
[2662]73
74        this->setConfigValues();
75
76        // load the corresponding score board
[6417]77        if (GameMode::showsGraphics() && !this->scoreboardTemplate_.empty())
[2662]78        {
[9667]79            this->scoreboard_ = new OverlayGroup(context);
[2662]80            this->scoreboard_->addTemplate(this->scoreboardTemplate_);
81            this->scoreboard_->setGametype(this);
82        }
83        else
84            this->scoreboard_ = 0;
[7801]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 */
[2072]90    }
[6417]91
[5929]92    Gametype::~Gametype()
93    {
94        if (this->isInitialized())
95        {
96            this->gtinfo_->destroy();
[7801]97            if( this->dedicatedAddBots_ )
98                delete this->dedicatedAddBots_;
99            if( this->dedicatedKillBots_ )
100                delete this->dedicatedKillBots_;
[5929]101        }
102    }
[2072]103
[2662]104    void Gametype::setConfigValues()
105    {
106        SetConfigValue(initialStartCountdown_, 3.0f);
107        SetConfigValue(bAutoStart_, false);
108        SetConfigValue(bForceSpawn_, false);
[9977]109        SetConfigValue(bAutoEnd_, true);
[2662]110        SetConfigValue(numberOfBots_, 0);
111        SetConfigValue(scoreboardTemplate_, "defaultScoreboard");
112    }
113
[2072]114    void Gametype::tick(float dt)
115    {
[2662]116        SUPER(Gametype, tick, dt);
[2072]117
[3033]118        //count timer
119        if (timerIsActive_)
120        {
121            if (this->timeLimit_ == 0)
122                this->time_ += dt;
123            else
124                this->time_ -= dt;
125        }
126
[8706]127        if (this->gtinfo_->isStartCountdownRunning() && !this->gtinfo_->hasStarted())
128            this->gtinfo_->countdownStartCountdown(dt);
[9260]129
[8706]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            }
[9260]138
[2072]139            this->checkStart();
[8706]140        }
141        else if (!this->gtinfo_->hasEnded())
[2171]142            this->spawnDeadPlayersIfRequested();
[2072]143
144        this->assignDefaultPawnsIfNeeded();
145    }
146
147    void Gametype::start()
148    {
[2826]149        this->addBots(this->numberOfBots_);
[8706]150        this->gtinfo_->start();
[2072]151        this->spawnPlayersIfRequested();
152    }
153
154    void Gametype::end()
155    {
[8706]156        this->gtinfo_->end();
[9977]157        if (this->bAutoEnd_)
[9980]158        {
159            this->showMenuTimer_.setTimer(3.0f, true, createExecutor(createFunctor(&Gametype::showMenu, this)));
[9977]160        }
[3033]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();
[3038]167
[9667]168                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(oldentity->getContext());
[3033]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        }
[2072]184    }
185
186    void Gametype::playerEntered(PlayerInfo* player)
187    {
[2662]188        this->players_[player].state_ = PlayerState::Joined;
[8706]189        this->gtinfo_->playerEntered(player);
[2072]190    }
191
[2826]192    bool Gametype::playerLeft(PlayerInfo* player)
[2072]193    {
[2662]194        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
[2072]195        if (it != this->players_.end())
196        {
197            this->players_.erase(it);
[2826]198            return true;
[2072]199        }
[2826]200        return false;
[2072]201    }
202
203    void Gametype::playerSwitched(PlayerInfo* player, Gametype* newgametype)
204    {
205    }
206
207    void Gametype::playerSwitchedBack(PlayerInfo* player, Gametype* oldgametype)
208    {
209    }
210
[2826]211    bool Gametype::playerChangedName(PlayerInfo* player)
[2072]212    {
213        if (this->players_.find(player) != this->players_.end())
214        {
215            if (player->getName() != player->getOldName())
216            {
[2826]217                return true;
[2072]218            }
219        }
[2826]220        return false;
[2072]221    }
222
223    void Gametype::pawnPreSpawn(Pawn* pawn)
224    {
225    }
226
227    void Gametype::pawnPostSpawn(Pawn* pawn)
228    {
229    }
230
[2826]231    void Gametype::playerPreSpawn(PlayerInfo* player)
[2072]232    {
[2826]233    }
[2662]234
[2826]235    void Gametype::playerPostSpawn(PlayerInfo* player)
236    {
237    }
[2662]238
[2826]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    {
[2662]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
[3099]273                if (killer && killer->getPlayer())
[2839]274                {
275                    std::map<PlayerInfo*, Player>::iterator it = this->players_.find(killer->getPlayer());
276                    if (it != this->players_.end())
[3099]277                    {
[2839]278                        it->second.frags_++;
[3099]279
[8327]280                        if (killer->getPlayer()->getClientID() != NETWORK_PEER_ID_UNKNOWN)
[5929]281                            this->gtinfo_->sendKillMessage("You killed " + victim->getPlayer()->getName(), killer->getPlayer()->getClientID());
[8327]282                        if (victim->getPlayer()->getClientID() != NETWORK_PEER_ID_UNKNOWN)
[5929]283                            this->gtinfo_->sendDeathMessage("You were killed by " + killer->getPlayer()->getName(), victim->getPlayer()->getClientID());
[3099]284                    }
[2839]285                }
[2662]286
[8706]287                if(victim->getPlayer()->isHumanPlayer())
288                    this->gtinfo_->pawnKilled(victim->getPlayer());
289
[9667]290                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(victim->getContext());
[2662]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
[8858]304                orxout(internal_warning) << "Killed Pawn was not in the playerlist" << endl;
[2662]305        }
[2072]306    }
307
[9348]308    void Gametype::playerScored(PlayerInfo* player, int score)
[2072]309    {
[2826]310        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
311        if (it != this->players_.end())
[9348]312            it->second.frags_ += score;
[2072]313    }
314
[2890]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
[2072]324    SpawnPoint* Gametype::getBestSpawnPoint(PlayerInfo* player) const
325    {
[8706]326        // If there is at least one SpawnPoint.
[2072]327        if (this->spawnpoints_.size() > 0)
328        {
[8706]329            // Fallback spawn point if there is no active one, choose a random one.
[7163]330            SpawnPoint* fallbackSpawnPoint = NULL;
[3196]331            unsigned int randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(this->spawnpoints_.size())));
[2072]332            unsigned int index = 0;
[8706]333            std::vector<SpawnPoint*> activeSpawnPoints;
[2072]334            for (std::set<SpawnPoint*>::const_iterator it = this->spawnpoints_.begin(); it != this->spawnpoints_.end(); ++it)
335            {
336                if (index == randomspawn)
[7163]337                    fallbackSpawnPoint = (*it);
338
[8706]339                if (*it != NULL && (*it)->isActive())
340                    activeSpawnPoints.push_back(*it);
[7163]341
342                ++index;
343            }
344
[8706]345            if(activeSpawnPoints.size() > 0)
[7163]346            {
[8706]347                randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(activeSpawnPoints.size())));
348                return activeSpawnPoints[randomspawn];
[2072]349            }
[7163]350
[8858]351            orxout(internal_warning) << "Fallback SpawnPoint was used because there were no active SpawnPoints." << endl;
[7163]352            return fallbackSpawnPoint;
[2072]353        }
354        return 0;
355    }
356
[2171]357    void Gametype::assignDefaultPawnsIfNeeded()
[2072]358    {
[2662]359        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
[2072]360        {
[2662]361            if (!it->first->getControllableEntity())
[2072]362            {
[2662]363                it->second.state_ = PlayerState::Dead;
364
[8706]365                if (!it->first->isReadyToSpawn() || !this->gtinfo_->hasStarted())
[2072]366                {
[3033]367                    this->spawnPlayerAsDefaultPawn(it->first);
368                    it->second.state_ = PlayerState::Dead;
[2072]369                }
370            }
371        }
372    }
373
374    void Gametype::checkStart()
375    {
[8706]376        if (!this->gtinfo_->hasStarted())
[2072]377        {
[8706]378            if (this->gtinfo_->isStartCountdownRunning())
[2072]379            {
[8706]380                if (this->gtinfo_->getStartCountdown() <= 0.0f)
[2072]381                {
[8706]382                    this->gtinfo_->stopStartCountdown();
[9016]383                    this->gtinfo_->setStartCountdown(0.0f);
[2072]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;
[2662]396                    bool hashumanplayers = false;
397                    for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
[2072]398                    {
[2171]399                        if (!it->first->isReadyToSpawn())
[2072]400                            allplayersready = false;
[2662]401                        if (it->first->isHumanPlayer())
402                            hashumanplayers = true;
[2072]403                    }
[9260]404
[2662]405                    if (allplayersready && hashumanplayers)
[2072]406                    {
[8079]407                        // If in developer's mode, there is no start countdown.
408                        if(Core::getInstance().inDevMode())
[8706]409                            this->start();
[8079]410                        else
[9261]411                        {
[8706]412                            this->gtinfo_->setStartCountdown(this->initialStartCountdown_);
[9261]413                            this->gtinfo_->startStartCountdown();
414                        }
[2072]415                    }
416                }
417            }
418        }
419    }
420
421    void Gametype::spawnPlayersIfRequested()
422    {
[2662]423        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
[8706]424        {
[2171]425            if (it->first->isReadyToSpawn() || this->bForceSpawn_)
426                this->spawnPlayer(it->first);
[8706]427        }
[2072]428    }
429
430    void Gametype::spawnDeadPlayersIfRequested()
431    {
[2662]432        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
433            if (it->second.state_ == PlayerState::Dead)
[2171]434                if (it->first->isReadyToSpawn() || this->bForceSpawn_)
435                    this->spawnPlayer(it->first);
[2072]436    }
437
438    void Gametype::spawnPlayer(PlayerInfo* player)
439    {
440        SpawnPoint* spawnpoint = this->getBestSpawnPoint(player);
441        if (spawnpoint)
442        {
[2826]443            this->playerPreSpawn(player);
[2072]444            player->startControl(spawnpoint->spawn());
[2662]445            this->players_[player].state_ = PlayerState::Alive;
[8706]446
447            if(player->isHumanPlayer())
448                this->gtinfo_->playerSpawned(player);
[9016]449
[2826]450            this->playerPostSpawn(player);
[2072]451        }
452        else
453        {
[8858]454            orxout(user_error) << "No SpawnPoints in current Gametype" << endl;
[2072]455            abort();
456        }
457    }
[2662]458
[3033]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
[9667]465            ControllableEntity* entity = this->defaultControllableEntity_.fabricate(spawn->getContext());
[3033]466            spawn->spawn(entity);
467            player->startControl(entity);
468        }
469        else
470        {
[8858]471            orxout(user_error) << "No SpawnPoints in current Gametype" << endl;
[3033]472            abort();
473        }
474    }
475
[2662]476    void Gametype::addBots(unsigned int amount)
477    {
478        for (unsigned int i = 0; i < amount; ++i)
[9667]479            this->botclass_.fabricate(this->getContext());
[2662]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            {
[5929]489                (it++)->destroy();
[2662]490                ++i;
491            }
[5929]492            else
493                ++it;
[2662]494        }
495    }
[3033]496
497    void Gametype::addTime(float t)
[3038]498    {
[3033]499        if (this->timeLimit_ == 0)
500          this->time_ -= t;
501        else
502          this->time_ += t;
503    }
504
505    void Gametype::removeTime(float t)
[3038]506    {
[3033]507        if (this->timeLimit_ == 0)
508          this->time_ += t;
509        else
510          this->time_ -= t;
511    }
512
513    void Gametype::resetTimer()
[3038]514    {
[3033]515        this->resetTimer(timeLimit_);
516    }
517
518    void Gametype::resetTimer(float t)
[3038]519    {
[3033]520        this->timeLimit_ = t;
521        this->time_ = t;
522    }
[9969]523
[9977]524    void Gametype::showMenu()
525    {
[9984]526        GSLevel::startMainMenu();
[9977]527    }
[10281]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    }
[2072]592}
Note: See TracBrowser for help on using the repository browser.