Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8079 was 8079, checked in by landauf, 13 years ago

merged usability branch back to trunk

incomplete summary of the changes in this branch:

  • enhanced keyboard navigation in GUIs
  • implemented new graphics menu and changeable window size at runtime
  • added developer mode
  • HUD shows if game is paused, game pauses if ingame menu is opened
  • removed a few obsolete commands and hid some that are more for internal use
  • numpad works in console and gui
  • faster loading of level info
  • enhanced usage of compositors (Shader class)
  • improved camera handling, configurable FOV and aspect ratio
  • Property svn:eol-style set to native
File size: 15.2 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_->bStartCountdownRunning_ && !this->gtinfo_->bStarted_)
124            this->gtinfo_->startCountdown_ -= dt;
125
126        if (!this->gtinfo_->bStarted_)
127            this->checkStart();
128        else if (!this->gtinfo_->bEnded_)
129            this->spawnDeadPlayersIfRequested();
130
131        this->assignDefaultPawnsIfNeeded();
132    }
133
134    void Gametype::start()
135    {
136        this->addBots(this->numberOfBots_);
137
138        this->gtinfo_->bStarted_ = true;
139
140        this->spawnPlayersIfRequested();
141    }
142
143    void Gametype::end()
144    {
145        this->gtinfo_->bEnded_ = true;
146
147        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
148        {
149            if (it->first->getControllableEntity())
150            {
151                ControllableEntity* oldentity = it->first->getControllableEntity();
152
153                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(oldentity);
154                if (oldentity->getCamera())
155                {
156                    entity->setPosition(oldentity->getCamera()->getWorldPosition());
157                    entity->setOrientation(oldentity->getCamera()->getWorldOrientation());
158                }
159                else
160                {
161                    entity->setPosition(oldentity->getWorldPosition());
162                    entity->setOrientation(oldentity->getWorldOrientation());
163                }
164
165                it->first->startControl(entity);
166            }
167            else
168                this->spawnPlayerAsDefaultPawn(it->first);
169        }
170    }
171
172    void Gametype::playerEntered(PlayerInfo* player)
173    {
174        this->players_[player].state_ = PlayerState::Joined;
175    }
176
177    bool Gametype::playerLeft(PlayerInfo* player)
178    {
179        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
180        if (it != this->players_.end())
181        {
182            this->players_.erase(it);
183            return true;
184        }
185        return false;
186    }
187
188    void Gametype::playerSwitched(PlayerInfo* player, Gametype* newgametype)
189    {
190    }
191
192    void Gametype::playerSwitchedBack(PlayerInfo* player, Gametype* oldgametype)
193    {
194    }
195
196    bool Gametype::playerChangedName(PlayerInfo* player)
197    {
198        if (this->players_.find(player) != this->players_.end())
199        {
200            if (player->getName() != player->getOldName())
201            {
202                return true;
203            }
204        }
205        return false;
206    }
207
208    void Gametype::pawnPreSpawn(Pawn* pawn)
209    {
210    }
211
212    void Gametype::pawnPostSpawn(Pawn* pawn)
213    {
214    }
215
216    void Gametype::playerPreSpawn(PlayerInfo* player)
217    {
218    }
219
220    void Gametype::playerPostSpawn(PlayerInfo* player)
221    {
222    }
223
224    void Gametype::playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn)
225    {
226    }
227
228    void Gametype::playerStopsControllingPawn(PlayerInfo* player, Pawn* pawn)
229    {
230    }
231
232    bool Gametype::allowPawnHit(Pawn* victim, Pawn* originator)
233    {
234        return true;
235    }
236
237    bool Gametype::allowPawnDamage(Pawn* victim, Pawn* originator)
238    {
239        return true;
240    }
241
242    bool Gametype::allowPawnDeath(Pawn* victim, Pawn* originator)
243    {
244        return true;
245    }
246
247    void Gametype::pawnKilled(Pawn* victim, Pawn* killer)
248    {
249        if (victim && victim->getPlayer())
250        {
251            std::map<PlayerInfo*, Player>::iterator it = this->players_.find(victim->getPlayer());
252            if (it != this->players_.end())
253            {
254                it->second.state_ = PlayerState::Dead;
255                it->second.killed_++;
256
257                // Reward killer
258                if (killer && killer->getPlayer())
259                {
260                    std::map<PlayerInfo*, Player>::iterator it = this->players_.find(killer->getPlayer());
261                    if (it != this->players_.end())
262                    {
263                        it->second.frags_++;
264
265                        if (killer->getPlayer()->getClientID() != CLIENTID_UNKNOWN)
266                            this->gtinfo_->sendKillMessage("You killed " + victim->getPlayer()->getName(), killer->getPlayer()->getClientID());
267                        if (victim->getPlayer()->getClientID() != CLIENTID_UNKNOWN)
268                            this->gtinfo_->sendDeathMessage("You were killed by " + killer->getPlayer()->getName(), victim->getPlayer()->getClientID());
269                    }
270                }
271
272                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(victim->getCreator());
273                if (victim->getCamera())
274                {
275                    entity->setPosition(victim->getCamera()->getWorldPosition());
276                    entity->setOrientation(victim->getCamera()->getWorldOrientation());
277                }
278                else
279                {
280                    entity->setPosition(victim->getWorldPosition());
281                    entity->setOrientation(victim->getWorldOrientation());
282                }
283                it->first->startControl(entity);
284            }
285            else
286                COUT(2) << "Warning: Killed Pawn was not in the playerlist" << std::endl;
287        }
288    }
289
290    void Gametype::playerScored(PlayerInfo* player)
291    {
292        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
293        if (it != this->players_.end())
294            it->second.frags_++;
295    }
296
297    int Gametype::getScore(PlayerInfo* player) const
298    {
299        std::map<PlayerInfo*, Player>::const_iterator it = this->players_.find(player);
300        if (it != this->players_.end())
301            return it->second.frags_;
302        else
303            return 0;
304    }
305
306    SpawnPoint* Gametype::getBestSpawnPoint(PlayerInfo* player) const
307    {
308        if (this->spawnpoints_.size() > 0)
309        {
310            SpawnPoint* fallbackSpawnPoint = NULL;
311            unsigned int randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(this->spawnpoints_.size())));
312            unsigned int index = 0;
313            std::set<SpawnPoint*> activeSpawnPoints = this->spawnpoints_;
314            for (std::set<SpawnPoint*>::const_iterator it = this->spawnpoints_.begin(); it != this->spawnpoints_.end(); ++it)
315            {
316                if (index == randomspawn)
317                    fallbackSpawnPoint = (*it);
318
319                if (!(*it)->isActive())
320                    activeSpawnPoints.erase(*it);
321
322                ++index;
323            }
324
325            randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(this->spawnpoints_.size())));
326            index = 0;
327            for (std::set<SpawnPoint*>::const_iterator it = activeSpawnPoints.begin(); it != activeSpawnPoints.end(); ++it)
328            {
329                if (index == randomspawn)
330                    return (*it);
331
332                ++index;
333            }
334
335            return fallbackSpawnPoint;
336        }
337        return 0;
338    }
339
340    void Gametype::assignDefaultPawnsIfNeeded()
341    {
342        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
343        {
344            if (!it->first->getControllableEntity())
345            {
346                it->second.state_ = PlayerState::Dead;
347
348                if (!it->first->isReadyToSpawn() || !this->gtinfo_->bStarted_)
349                {
350                    this->spawnPlayerAsDefaultPawn(it->first);
351                    it->second.state_ = PlayerState::Dead;
352                }
353            }
354        }
355    }
356
357    void Gametype::checkStart()
358    {
359        if (!this->gtinfo_->bStarted_)
360        {
361            if (this->gtinfo_->bStartCountdownRunning_)
362            {
363                if (this->gtinfo_->startCountdown_ <= 0)
364                {
365                    this->gtinfo_->bStartCountdownRunning_ = false;
366                    this->gtinfo_->startCountdown_ = 0;
367                    this->start();
368                }
369            }
370            else if (this->players_.size() > 0)
371            {
372                if (this->bAutoStart_)
373                {
374                    this->start();
375                }
376                else
377                {
378                    bool allplayersready = true;
379                    bool hashumanplayers = false;
380                    for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
381                    {
382                        if (!it->first->isReadyToSpawn())
383                            allplayersready = false;
384                        if (it->first->isHumanPlayer())
385                            hashumanplayers = true;
386                    }
387                    if (allplayersready && hashumanplayers)
388                    {
389                        // If in developer's mode, there is no start countdown.
390                        if(Core::getInstance().inDevMode())
391                            this->gtinfo_->startCountdown_ = 0;
392                        else
393                            this->gtinfo_->startCountdown_ = this->initialStartCountdown_;
394                        this->gtinfo_->bStartCountdownRunning_ = true;
395                    }
396                }
397            }
398        }
399    }
400
401    void Gametype::spawnPlayersIfRequested()
402    {
403        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
404            if (it->first->isReadyToSpawn() || this->bForceSpawn_)
405                this->spawnPlayer(it->first);
406    }
407
408    void Gametype::spawnDeadPlayersIfRequested()
409    {
410        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
411            if (it->second.state_ == PlayerState::Dead)
412                if (it->first->isReadyToSpawn() || this->bForceSpawn_)
413                    this->spawnPlayer(it->first);
414    }
415
416    void Gametype::spawnPlayer(PlayerInfo* player)
417    {
418        SpawnPoint* spawnpoint = this->getBestSpawnPoint(player);
419        if (spawnpoint)
420        {
421            this->playerPreSpawn(player);
422            player->startControl(spawnpoint->spawn());
423            this->players_[player].state_ = PlayerState::Alive;
424            this->playerPostSpawn(player);
425        }
426        else
427        {
428            COUT(1) << "Error: No SpawnPoints in current Gametype" << std::endl;
429            abort();
430        }
431    }
432
433    void Gametype::spawnPlayerAsDefaultPawn(PlayerInfo* player)
434    {
435        SpawnPoint* spawn = this->getBestSpawnPoint(player);
436        if (spawn)
437        {
438            // force spawn at spawnpoint with default pawn
439            ControllableEntity* entity = this->defaultControllableEntity_.fabricate(spawn);
440            spawn->spawn(entity);
441            player->startControl(entity);
442        }
443        else
444        {
445            COUT(1) << "Error: No SpawnPoints in current Gametype" << std::endl;
446            abort();
447        }
448    }
449
450    void Gametype::addBots(unsigned int amount)
451    {
452        for (unsigned int i = 0; i < amount; ++i)
453            this->botclass_.fabricate(this);
454    }
455
456    void Gametype::killBots(unsigned int amount)
457    {
458        unsigned int i = 0;
459        for (ObjectList<Bot>::iterator it = ObjectList<Bot>::begin(); (it != ObjectList<Bot>::end()) && ((amount == 0) || (i < amount)); )
460        {
461            if (it->getGametype() == this)
462            {
463                (it++)->destroy();
464                ++i;
465            }
466            else
467                ++it;
468        }
469    }
470
471    void Gametype::addTime(float t)
472    {
473        if (this->timeLimit_ == 0)
474          this->time_ -= t;
475        else
476          this->time_ += t;
477    }
478
479    void Gametype::removeTime(float t)
480    {
481        if (this->timeLimit_ == 0)
482          this->time_ += t;
483        else
484          this->time_ -= t;
485    }
486
487    void Gametype::resetTimer()
488    {
489        this->resetTimer(timeLimit_);
490    }
491
492    void Gametype::resetTimer(float t)
493    {
494        this->timeLimit_ = t;
495        this->time_ = t;
496    }
497}
Note: See TracBrowser for help on using the repository browser.