Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutoriallevel3/src/orxonox/gametypes/Gametype.cc @ 8453

Last change on this file since 8453 was 8453, checked in by dafrick, 13 years ago

Merging tutoriallevel2 branch into tutoriallevel3 branch.

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