Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5929 was 5929, checked in by rgrieder, 15 years ago

Merged core5 branch back to the trunk.
Key features include clean level unloading and an extended XML event system.

Two important notes:
Delete your keybindings.ini files! * or you will still get parser errors when loading the key bindings.
Delete build_dir/lib/modules/libgamestates.module! * or orxonox won't start.
Best thing to do is to delete the build folder ;)

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