Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core5/src/orxonox/gametypes/Gametype.cc @ 5827

Last change on this file since 5827 was 5827, checked in by landauf, 15 years ago

(hopefully) a small fix in Gametype (not sure if this works with the network though, because the creator of a new object is deleted in the next line. but I think we fixed this problem, didn't we?)

This bug caused a crash if the creator (usually a SpawnPoint) of a Pawn was already deleted (which is the case in our UnderAttack level where the SpawnPoints are attached to the Destroyer - with the destruction of the Destroyer, the SpawnPoints were also removed.)

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