Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10479 was 10479, checked in by landauf, 6 years ago

moved config values and all related functions from Game and Core to GameConfig and CoreConfig respectively. this ensures that no framework features are used by Game and Core before Core itself initialized the framework.

  • Property svn:eol-style set to native
File size: 18.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 *      ...
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/ConsoleCommandIncludes.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    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
57    RegisterUnloadableClass(Gametype);
58
59    Gametype::Gametype(Context* context) : BaseObject(context)
60    {
61        RegisterObject(Gametype);
62
63        this->gtinfo_ = new GametypeInfo(context);
64
65        this->setGametype(SmartPtr<Gametype>(this, false));
66
67        this->defaultControllableEntity_ = Class(Spectator);
68
69        this->bAutoStart_ = false;
70        this->bForceSpawn_ = false;
71        this->bAutoEnd_ = true;
72        this->numberOfBots_ = 0;
73
74        this->timeLimit_ = 0;
75        this->time_ = 0;
76        this->timerIsActive_ = false;
77
78        this->initialStartCountdown_ = 3;
79
80        this->setConfigValues();
81
82        // load the corresponding score board
83        if (GameMode::showsGraphics() && !this->scoreboardTemplate_.empty())
84        {
85            this->scoreboard_ = new OverlayGroup(context);
86            this->scoreboard_->addTemplate(this->scoreboardTemplate_);
87            this->scoreboard_->setGametype(this);
88        }
89        else
90            this->scoreboard_ = 0;
91
92        ModifyConsoleCommand(__CC_addBots_name).setObject(this);
93        ModifyConsoleCommand(__CC_killBots_name).setObject(this);
94    }
95
96    Gametype::~Gametype()
97    {
98        if (this->isInitialized())
99        {
100            this->gtinfo_->destroy();
101
102            ModifyConsoleCommand(__CC_addBots_name).setObject(NULL);
103            ModifyConsoleCommand(__CC_killBots_name).setObject(NULL);
104        }
105    }
106
107    void Gametype::setConfigValues()
108    {
109        SetConfigValue(initialStartCountdown_, 3.0f);
110        SetConfigValue(bAutoStart_, false);
111        SetConfigValue(bForceSpawn_, false);
112        SetConfigValue(bAutoEnd_, true);
113        SetConfigValue(numberOfBots_, 0);
114        SetConfigValue(scoreboardTemplate_, "defaultScoreboard");
115    }
116
117    void Gametype::tick(float dt)
118    {
119        SUPER(Gametype, tick, dt);
120
121        //count timer
122        if (timerIsActive_)
123        {
124            if (this->timeLimit_ == 0)
125                this->time_ += dt;
126            else
127                this->time_ -= dt;
128        }
129
130        if (this->gtinfo_->isStartCountdownRunning() && !this->gtinfo_->hasStarted())
131            this->gtinfo_->countdownStartCountdown(dt);
132
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            }
141
142            this->checkStart();
143        }
144        else if (!this->gtinfo_->hasEnded())
145            this->spawnDeadPlayersIfRequested();
146
147        this->assignDefaultPawnsIfNeeded();
148    }
149
150    void Gametype::start()
151    {
152        this->addBots(this->numberOfBots_);
153        this->gtinfo_->start();
154        this->spawnPlayersIfRequested();
155    }
156
157    void Gametype::end()
158    {
159        this->gtinfo_->end();
160        if (this->bAutoEnd_)
161        {
162            this->showMenuTimer_.setTimer(3.0f, true, createExecutor(createFunctor(&Gametype::showMenu, this)));
163        }
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();
170
171                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(oldentity->getContext());
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        }
187    }
188
189    void Gametype::playerEntered(PlayerInfo* player)
190    {
191        this->players_[player].state_ = PlayerState::Joined;
192        this->gtinfo_->playerEntered(player);
193    }
194
195    bool Gametype::playerLeft(PlayerInfo* player)
196    {
197        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
198        if (it != this->players_.end())
199        {
200            this->players_.erase(it);
201            return true;
202        }
203        return false;
204    }
205
206    void Gametype::playerSwitched(PlayerInfo* player, Gametype* newgametype)
207    {
208    }
209
210    void Gametype::playerSwitchedBack(PlayerInfo* player, Gametype* oldgametype)
211    {
212    }
213
214    bool Gametype::playerChangedName(PlayerInfo* player)
215    {
216        if (this->players_.find(player) != this->players_.end())
217        {
218            if (player->getName() != player->getOldName())
219            {
220                return true;
221            }
222        }
223        return false;
224    }
225
226    void Gametype::pawnPreSpawn(Pawn* pawn)
227    {
228    }
229
230    void Gametype::pawnPostSpawn(Pawn* pawn)
231    {
232    }
233
234    void Gametype::playerPreSpawn(PlayerInfo* player)
235    {
236    }
237
238    void Gametype::playerPostSpawn(PlayerInfo* player)
239    {
240    }
241
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    {
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
276                if (killer && killer->getPlayer())
277                {
278                    std::map<PlayerInfo*, Player>::iterator it = this->players_.find(killer->getPlayer());
279                    if (it != this->players_.end())
280                    {
281                        it->second.frags_++;
282
283                        if (killer->getPlayer()->getClientID() != NETWORK_PEER_ID_UNKNOWN)
284                            this->gtinfo_->sendKillMessage("You killed " + victim->getPlayer()->getName(), killer->getPlayer()->getClientID());
285                        if (victim->getPlayer()->getClientID() != NETWORK_PEER_ID_UNKNOWN)
286                            this->gtinfo_->sendDeathMessage("You were killed by " + killer->getPlayer()->getName(), victim->getPlayer()->getClientID());
287                    }
288                }
289
290                if(victim->getPlayer()->isHumanPlayer())
291                    this->gtinfo_->pawnKilled(victim->getPlayer());
292
293                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(victim->getContext());
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
307                orxout(internal_warning) << "Killed Pawn was not in the playerlist" << endl;
308        }
309    }
310
311    void Gametype::playerScored(PlayerInfo* player, int score)
312    {
313        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
314        if (it != this->players_.end())
315            it->second.frags_ += score;
316    }
317
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
327    SpawnPoint* Gametype::getBestSpawnPoint(PlayerInfo* player) const
328    {
329        // If there is at least one SpawnPoint.
330        if (this->spawnpoints_.size() > 0)
331        {
332            // Fallback spawn point if there is no active one, choose a random one.
333            SpawnPoint* fallbackSpawnPoint = NULL;
334            unsigned int randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(this->spawnpoints_.size())));
335            unsigned int index = 0;
336            std::vector<SpawnPoint*> activeSpawnPoints;
337            for (std::set<SpawnPoint*>::const_iterator it = this->spawnpoints_.begin(); it != this->spawnpoints_.end(); ++it)
338            {
339                if (index == randomspawn)
340                    fallbackSpawnPoint = (*it);
341
342                if (*it != NULL && (*it)->isActive())
343                    activeSpawnPoints.push_back(*it);
344
345                ++index;
346            }
347
348            if(activeSpawnPoints.size() > 0)
349            {
350                randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(activeSpawnPoints.size())));
351                return activeSpawnPoints[randomspawn];
352            }
353
354            orxout(internal_warning) << "Fallback SpawnPoint was used because there were no active SpawnPoints." << endl;
355            return fallbackSpawnPoint;
356        }
357        return 0;
358    }
359
360    void Gametype::assignDefaultPawnsIfNeeded()
361    {
362        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
363        {
364            if (!it->first->getControllableEntity())
365            {
366                it->second.state_ = PlayerState::Dead;
367
368                if (!it->first->isReadyToSpawn() || !this->gtinfo_->hasStarted())
369                {
370                    this->spawnPlayerAsDefaultPawn(it->first);
371                    it->second.state_ = PlayerState::Dead;
372                }
373            }
374        }
375    }
376
377    void Gametype::checkStart()
378    {
379        if (!this->gtinfo_->hasStarted())
380        {
381            if (this->gtinfo_->isStartCountdownRunning())
382            {
383                if (this->gtinfo_->getStartCountdown() <= 0.0f)
384                {
385                    this->gtinfo_->stopStartCountdown();
386                    this->gtinfo_->setStartCountdown(0.0f);
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;
399                    bool hashumanplayers = false;
400                    for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
401                    {
402                        if (!it->first->isReadyToSpawn())
403                            allplayersready = false;
404                        if (it->first->isHumanPlayer())
405                            hashumanplayers = true;
406                    }
407
408                    if (allplayersready && hashumanplayers)
409                    {
410                        // If in developer's mode, there is no start countdown.
411                        if(Core::getInstance().getConfig()->inDevMode())
412                            this->start();
413                        else
414                        {
415                            this->gtinfo_->setStartCountdown(this->initialStartCountdown_);
416                            this->gtinfo_->startStartCountdown();
417                        }
418                    }
419                }
420            }
421        }
422    }
423
424    void Gametype::spawnPlayersIfRequested()
425    {
426        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
427        {
428            if (it->first->isReadyToSpawn() || this->bForceSpawn_)
429                this->spawnPlayer(it->first);
430        }
431    }
432
433    void Gametype::spawnDeadPlayersIfRequested()
434    {
435        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
436            if (it->second.state_ == PlayerState::Dead)
437                if (it->first->isReadyToSpawn() || this->bForceSpawn_)
438                    this->spawnPlayer(it->first);
439    }
440
441    void Gametype::spawnPlayer(PlayerInfo* player)
442    {
443        SpawnPoint* spawnpoint = this->getBestSpawnPoint(player);
444        if (spawnpoint)
445        {
446            this->playerPreSpawn(player);
447            player->startControl(spawnpoint->spawn());
448            this->players_[player].state_ = PlayerState::Alive;
449
450            if(player->isHumanPlayer())
451                this->gtinfo_->playerSpawned(player);
452
453            this->playerPostSpawn(player);
454        }
455        else
456        {
457            orxout(user_error) << "No SpawnPoints in current Gametype" << endl;
458            abort();
459        }
460    }
461
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
468            ControllableEntity* entity = this->defaultControllableEntity_.fabricate(spawn->getContext());
469            spawn->spawn(entity);
470            player->startControl(entity);
471        }
472        else
473        {
474            orxout(user_error) << "No SpawnPoints in current Gametype" << endl;
475            abort();
476        }
477    }
478
479    void Gametype::addBots(unsigned int amount)
480    {
481        for (unsigned int i = 0; i < amount; ++i)
482            this->botclass_.fabricate(this->getContext());
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            {
492                (it++)->destroy();
493                ++i;
494            }
495            else
496                ++it;
497        }
498    }
499
500    void Gametype::addTime(float t)
501    {
502        if (this->timeLimit_ == 0)
503          this->time_ -= t;
504        else
505          this->time_ += t;
506    }
507
508    void Gametype::removeTime(float t)
509    {
510        if (this->timeLimit_ == 0)
511          this->time_ += t;
512        else
513          this->time_ -= t;
514    }
515
516    void Gametype::resetTimer()
517    {
518        this->resetTimer(timeLimit_);
519    }
520
521    void Gametype::resetTimer(float t)
522    {
523        this->timeLimit_ = t;
524        this->time_ = t;
525    }
526
527    void Gametype::showMenu()
528    {
529        GSLevel::startMainMenu();
530    }
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    }
595}
Note: See TracBrowser for help on using the repository browser.