Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Merging presentation branch back into trunk.
There are many new features and also a lot of other changes and bugfixes, if you want to know, digg through the svn log.
Not everything is yet working as it should, but it should be fairly stable. If you habe any bug reports, just send me an email.

  • Property svn:eol-style set to native
File size: 16.0 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->bAutoStart_ = false;
62        this->bForceSpawn_ = false;
63        this->numberOfBots_ = 0;
64
65        this->timeLimit_ = 0;
66        this->time_ = 0;
67        this->timerIsActive_ = false;
68
69        this->initialStartCountdown_ = 3;
70
71        this->setConfigValues();
72
73        // load the corresponding score board
74        if (GameMode::showsGraphics() && !this->scoreboardTemplate_.empty())
75        {
76            this->scoreboard_ = new OverlayGroup(this);
77            this->scoreboard_->addTemplate(this->scoreboardTemplate_);
78            this->scoreboard_->setGametype(this);
79        }
80        else
81            this->scoreboard_ = 0;
82
83        /* HACK HACK HACK */
84        this->dedicatedAddBots_ = createConsoleCommand( "dedicatedAddBots", createExecutor( createFunctor(&Gametype::addBots, this) ) );
85        this->dedicatedKillBots_ = createConsoleCommand( "dedicatedKillBots", createExecutor( createFunctor(&Gametype::killBots, this) ) );
86        /* HACK HACK HACK */
87    }
88
89    Gametype::~Gametype()
90    {
91        if (this->isInitialized())
92        {
93            this->gtinfo_->destroy();
94            if( this->dedicatedAddBots_ )
95                delete this->dedicatedAddBots_;
96            if( this->dedicatedKillBots_ )
97                delete this->dedicatedKillBots_;
98        }
99    }
100
101    void Gametype::setConfigValues()
102    {
103        SetConfigValue(initialStartCountdown_, 3.0f);
104        SetConfigValue(bAutoStart_, false);
105        SetConfigValue(bForceSpawn_, false);
106        SetConfigValue(numberOfBots_, 0);
107        SetConfigValue(scoreboardTemplate_, "defaultScoreboard");
108    }
109
110    void Gametype::tick(float dt)
111    {
112        SUPER(Gametype, tick, dt);
113
114        //count timer
115        if (timerIsActive_)
116        {
117            if (this->timeLimit_ == 0)
118                this->time_ += dt;
119            else
120                this->time_ -= dt;
121        }
122
123        if (this->gtinfo_->isStartCountdownRunning() && !this->gtinfo_->hasStarted())
124            this->gtinfo_->countdownStartCountdown(dt);
125
126        if (!this->gtinfo_->hasStarted())
127        {
128            for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
129            {
130                // Inform the GametypeInfo that the player is ready to spawn.
131                if(it->first->isHumanPlayer() && it->first->isReadyToSpawn())
132                    this->gtinfo_->playerReadyToSpawn(it->first);
133            }
134                   
135            this->checkStart();
136        }
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        this->gtinfo_->playerEntered(player);
185    }
186
187    bool Gametype::playerLeft(PlayerInfo* player)
188    {
189        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
190        if (it != this->players_.end())
191        {
192            this->players_.erase(it);
193            return true;
194        }
195        return false;
196    }
197
198    void Gametype::playerSwitched(PlayerInfo* player, Gametype* newgametype)
199    {
200    }
201
202    void Gametype::playerSwitchedBack(PlayerInfo* player, Gametype* oldgametype)
203    {
204    }
205
206    bool Gametype::playerChangedName(PlayerInfo* player)
207    {
208        if (this->players_.find(player) != this->players_.end())
209        {
210            if (player->getName() != player->getOldName())
211            {
212                return true;
213            }
214        }
215        return false;
216    }
217
218    void Gametype::pawnPreSpawn(Pawn* pawn)
219    {
220    }
221
222    void Gametype::pawnPostSpawn(Pawn* pawn)
223    {
224    }
225
226    void Gametype::playerPreSpawn(PlayerInfo* player)
227    {
228    }
229
230    void Gametype::playerPostSpawn(PlayerInfo* player)
231    {
232    }
233
234    void Gametype::playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn)
235    {
236    }
237
238    void Gametype::playerStopsControllingPawn(PlayerInfo* player, Pawn* pawn)
239    {
240    }
241
242    bool Gametype::allowPawnHit(Pawn* victim, Pawn* originator)
243    {
244        return true;
245    }
246
247    bool Gametype::allowPawnDamage(Pawn* victim, Pawn* originator)
248    {
249        return true;
250    }
251
252    bool Gametype::allowPawnDeath(Pawn* victim, Pawn* originator)
253    {
254        return true;
255    }
256
257    void Gametype::pawnKilled(Pawn* victim, Pawn* killer)
258    {
259        if (victim && victim->getPlayer())
260        {
261            std::map<PlayerInfo*, Player>::iterator it = this->players_.find(victim->getPlayer());
262            if (it != this->players_.end())
263            {
264                it->second.state_ = PlayerState::Dead;
265                it->second.killed_++;
266
267                // Reward killer
268                if (killer && killer->getPlayer())
269                {
270                    std::map<PlayerInfo*, Player>::iterator it = this->players_.find(killer->getPlayer());
271                    if (it != this->players_.end())
272                    {
273                        it->second.frags_++;
274
275                        if (killer->getPlayer()->getClientID() != NETWORK_PEER_ID_UNKNOWN)
276                            this->gtinfo_->sendKillMessage("You killed " + victim->getPlayer()->getName(), killer->getPlayer()->getClientID());
277                        if (victim->getPlayer()->getClientID() != NETWORK_PEER_ID_UNKNOWN)
278                            this->gtinfo_->sendDeathMessage("You were killed by " + killer->getPlayer()->getName(), victim->getPlayer()->getClientID());
279                    }
280                }
281
282                if(victim->getPlayer()->isHumanPlayer())
283                    this->gtinfo_->pawnKilled(victim->getPlayer());
284
285                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(victim->getCreator());
286                if (victim->getCamera())
287                {
288                    entity->setPosition(victim->getCamera()->getWorldPosition());
289                    entity->setOrientation(victim->getCamera()->getWorldOrientation());
290                }
291                else
292                {
293                    entity->setPosition(victim->getWorldPosition());
294                    entity->setOrientation(victim->getWorldOrientation());
295                }
296                it->first->startControl(entity);
297            }
298            else
299                COUT(2) << "Warning: Killed Pawn was not in the playerlist" << std::endl;
300        }
301    }
302
303    void Gametype::playerScored(PlayerInfo* player)
304    {
305        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
306        if (it != this->players_.end())
307            it->second.frags_++;
308    }
309
310    int Gametype::getScore(PlayerInfo* player) const
311    {
312        std::map<PlayerInfo*, Player>::const_iterator it = this->players_.find(player);
313        if (it != this->players_.end())
314            return it->second.frags_;
315        else
316            return 0;
317    }
318
319    SpawnPoint* Gametype::getBestSpawnPoint(PlayerInfo* player) const
320    {
321        // If there is at least one SpawnPoint.
322        if (this->spawnpoints_.size() > 0)
323        {
324            // Fallback spawn point if there is no active one, choose a random one.
325            SpawnPoint* fallbackSpawnPoint = NULL;
326            unsigned int randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(this->spawnpoints_.size())));
327            unsigned int index = 0;
328            std::vector<SpawnPoint*> activeSpawnPoints;
329            for (std::set<SpawnPoint*>::const_iterator it = this->spawnpoints_.begin(); it != this->spawnpoints_.end(); ++it)
330            {
331                if (index == randomspawn)
332                    fallbackSpawnPoint = (*it);
333
334                if (*it != NULL && (*it)->isActive())
335                    activeSpawnPoints.push_back(*it);
336
337                ++index;
338            }
339
340            if(activeSpawnPoints.size() > 0)
341            {
342                randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(activeSpawnPoints.size())));
343                return activeSpawnPoints[randomspawn];
344            }
345
346            COUT(2) << "Warning: Fallback SpawnPoint was used, because there were no active SpawnPoints." << endl;
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                    if (allplayersready && hashumanplayers)
400                    {
401                        // If in developer's mode, there is no start countdown.
402                        if(Core::getInstance().inDevMode())
403                            this->start();
404                        else
405                            this->gtinfo_->setStartCountdown(this->initialStartCountdown_);
406                        this->gtinfo_->startStartCountdown();
407                    }
408                }
409            }
410        }
411    }
412
413    void Gametype::spawnPlayersIfRequested()
414    {
415        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
416        {
417            if (it->first->isReadyToSpawn() || this->bForceSpawn_)
418                this->spawnPlayer(it->first);
419        }
420    }
421
422    void Gametype::spawnDeadPlayersIfRequested()
423    {
424        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
425            if (it->second.state_ == PlayerState::Dead)
426                if (it->first->isReadyToSpawn() || this->bForceSpawn_)
427                    this->spawnPlayer(it->first);
428    }
429
430    void Gametype::spawnPlayer(PlayerInfo* player)
431    {
432        SpawnPoint* spawnpoint = this->getBestSpawnPoint(player);
433        if (spawnpoint)
434        {
435            this->playerPreSpawn(player);
436            player->startControl(spawnpoint->spawn());
437            this->players_[player].state_ = PlayerState::Alive;
438
439            if(player->isHumanPlayer())
440                this->gtinfo_->playerSpawned(player);
441           
442            this->playerPostSpawn(player);
443        }
444        else
445        {
446            COUT(1) << "Error: No SpawnPoints in current Gametype" << std::endl;
447            abort();
448        }
449    }
450
451    void Gametype::spawnPlayerAsDefaultPawn(PlayerInfo* player)
452    {
453        SpawnPoint* spawn = this->getBestSpawnPoint(player);
454        if (spawn)
455        {
456            // force spawn at spawnpoint with default pawn
457            ControllableEntity* entity = this->defaultControllableEntity_.fabricate(spawn);
458            spawn->spawn(entity);
459            player->startControl(entity);
460        }
461        else
462        {
463            COUT(1) << "Error: No SpawnPoints in current Gametype" << std::endl;
464            abort();
465        }
466    }
467
468    void Gametype::addBots(unsigned int amount)
469    {
470        for (unsigned int i = 0; i < amount; ++i)
471            this->botclass_.fabricate(this);
472    }
473
474    void Gametype::killBots(unsigned int amount)
475    {
476        unsigned int i = 0;
477        for (ObjectList<Bot>::iterator it = ObjectList<Bot>::begin(); (it != ObjectList<Bot>::end()) && ((amount == 0) || (i < amount)); )
478        {
479            if (it->getGametype() == this)
480            {
481                (it++)->destroy();
482                ++i;
483            }
484            else
485                ++it;
486        }
487    }
488
489    void Gametype::addTime(float t)
490    {
491        if (this->timeLimit_ == 0)
492          this->time_ -= t;
493        else
494          this->time_ += t;
495    }
496
497    void Gametype::removeTime(float t)
498    {
499        if (this->timeLimit_ == 0)
500          this->time_ += t;
501        else
502          this->time_ -= t;
503    }
504
505    void Gametype::resetTimer()
506    {
507        this->resetTimer(timeLimit_);
508    }
509
510    void Gametype::resetTimer(float t)
511    {
512        this->timeLimit_ = t;
513        this->time_ = t;
514    }
515}
Note: See TracBrowser for help on using the repository browser.