Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core7/src/orxonox/gametypes/Gametype.cc @ 10349

Last change on this file since 10349 was 10349, checked in by landauf, 9 years ago

removed hack. addBots/killBots is now part of Gametype

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