Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/dynamicmatch/src/orxonox/gametypes/Dynamicmatch.cc @ 6848

Last change on this file since 6848 was 6848, checked in by jo, 14 years ago

enhanced level, Teamspawnpoints - almost playable version

  • Property svn:eol-style set to native
File size: 18.3 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 *      Johannes Ritz
24 *   Co-authors:
25 *      ...
26 *
27 */
28//TODO: killers integrieren ; ArtificialController anpassen);
29//pig punkte vergeben pro Zeit!
30//killerfarbe schwarz; evtl. eigenes Raumfahrzeug;
31//Low; Codeoptimierung und Dokumentation
32
33/*
34short gaming manual:
35There are three different parties a player can belong to: victim, chaser or killer
36Every player starts as chaser. As long as there are not enough victims and killers, you can change your and other player's parties by shooting them.
37In order to win you have to earn as much points as possible:
38- as victim by escaping the chasers
39- as chaser by shooting the victim
40- as killer by killing the chasers
41
42
43What you shouldn't do is shooting at players of your own party. By doing so your score will decrease.
44P.S: If you don't want to be a victim: Get rid of your part by shooting a chaser.
45*/
46#include "Dynamicmatch.h"
47
48#include "util/Convert.h"
49#include "core/CoreIncludes.h"
50#include "network/Host.h"
51#include "infos/PlayerInfo.h"
52#include "worldentities/pawns/Pawn.h"
53#include "worldentities/pawns/SpaceShip.h"
54#include "core/ConfigValueIncludes.h"
55#include "interfaces/TeamColourable.h"
56#include "items/Engine.h"
57#include "tools/Timer.h"
58#include "worldentities/TeamSpawnPoint.h"
59
60namespace orxonox
61{
62    CreateUnloadableFactory(Dynamicmatch);
63
64    Dynamicmatch::Dynamicmatch(BaseObject* creator) : Gametype(creator)
65    {
66        RegisterObject(Dynamicmatch);
67        this->gameTime_ = 180;
68        this->setConfigValues();
69        this->chaser=0;
70        this->piggy=1;
71        this->killer=2;
72        this->notEnoughPigs=false;
73        this->notEnoughKillers=false;
74        this->notEnoughChasers=false;
75        this->gameEnded_ =false;
76        this->timesequence_ = static_cast<int>(this->gameTime_);
77        this->friendlyfire=true;
78        this->numberOf[chaser]=0;
79        this->numberOf[piggy]=0;
80        this->numberOf[killer]=0;
81        this->tutorial=true;
82        this->pointsPerTime=0.0f;
83    }
84
85    void Dynamicmatch::setConfigValues()
86    {
87        SetConfigValue(gameTime_, 180);
88        SetConfigValue(friendlyfire, true);
89        SetConfigValue(tutorial, true);
90        static ColourValue colours[] =
91        {
92            ColourValue(0.3f, 0.3f, 1.0f),      //chasercolour
93            ColourValue(1.0f, 0.3f, 0.3f),      //piggycolour
94            ColourValue(0.3f, 1.0f, 0.3f)       //killercolour  what about black: 0.0f, 0.0f, 0.0f
95           
96        };
97        static std::vector<ColourValue> defaultcolours(colours, colours + sizeof(colours) / sizeof(ColourValue));
98
99        SetConfigValue(partyColours_, defaultcolours);
100    }
101
102    bool Dynamicmatch::allowPawnDamage(Pawn* victim, Pawn* originator)
103    {   
104        if (!originator||!victim)
105        {return false;}
106        if (victim && victim->getPlayer()) //&& originator && originator->getPlayer() ??
107        {
108        int target= playerParty_[victim->getPlayer()];
109        int source= playerParty_[originator->getPlayer()];
110
111            //Case: Not Enough Pigs: party change (= party management)
112            if (notEnoughPigs)
113            {
114                       
115                numberOf[target]--;                             //decrease numberof victims's party
116                playerParty_[victim->getPlayer()]=piggy;        //victim's new party: pig
117                setPlayerColour(victim->getPlayer());           //victim's new colour
118                numberOf[piggy]++;                              //party switch: number of players is not affected (decrease and increase)
119                    if (notEnoughKillers)                       //reward the originator
120                    {
121                        numberOf[source]--;                     //decrease numberof originator's party
122                        playerParty_[originator->getPlayer()]=killer;           //originator's new party: killer
123                        setPlayerColour(originator->getPlayer());               //originator's new colour
124                        numberOf[killer]++;
125                    }
126                evaluatePlayerParties();                        //check if the party change has to trigger futher party changes
127                       
128                //Give new pig boost
129                SpaceShip* spaceship = dynamic_cast<SpaceShip*>(victim);
130                if (spaceship && spaceship->getEngine())
131                {
132                    spaceship->getEngine()->setSpeedFactor(5);
133                    WeakPtr<Engine>* ptr = new WeakPtr<Engine>(spaceship->getEngine());
134                    new Timer(10, false, &createExecutor(createFunctor(&Dynamicmatch::resetSpeedFactor, this))->setDefaultValue(0, ptr), true);
135                }
136            }
137
138            //Case: notEnoughKillers: party change
139            else if (notEnoughKillers)
140            {
141                numberOf[target]--;     //decrease numberof victims's party
142                playerParty_[victim->getPlayer()]=killer;       //victim's new party: killer
143                setPlayerColour(victim->getPlayer());           //victim colour
144                numberOf[killer]++;                             //party switch: number of players is not affected (decrease and increase)
145                evaluatePlayerParties();                        //check if the party change has to trigger futher party changes
146            }
147            //Case: notEnoughChasers: party change
148            else if (notEnoughChasers)
149            {
150                numberOf[target]--;     //decrease numberof victims's party
151                playerParty_[victim->getPlayer()]=chaser;       //victim's new party: chaser
152                setPlayerColour(victim->getPlayer());           //victim colour
153                numberOf[chaser]++;                             //party switch: number of players is not affected (decrease and increase)
154                evaluatePlayerParties();                        //check if the party change has to trigger futher party changes
155            }
156
157            //Case: chaser vs. killer
158            else if ((source == killer && target == chaser)||(target == killer && source == chaser ))
159            {
160                return true;
161            }
162
163            //Case: a chaser hits piggy
164            else if ((source==chaser)&&(target==piggy))
165            {
166                std::map<PlayerInfo*, Player>::iterator it = this->players_.find(originator->getPlayer());
167                if (it != this->players_.end())
168                    {
169                        it->second.frags_++;
170                    }
171            }
172            //Case: piggy hits chaser
173            else if (source==piggy&&target==chaser)
174            {
175                //partyswitch: victim bcomes piggy and the originator(piggy) becomes chaser
176                playerParty_[victim->getPlayer()]=piggy;
177                playerParty_[originator->getPlayer()]=chaser;
178
179                //party switch -> colour switch         
180                setPlayerColour(victim->getPlayer()); //victim colour
181                setPlayerColour(originator->getPlayer());//originator colour
182
183                //Give new pig boost
184                SpaceShip* spaceship = dynamic_cast<SpaceShip*>(victim);
185                if (spaceship && spaceship->getEngine())
186                {
187                    spaceship->getEngine()->setSpeedFactor(5);
188                    WeakPtr<Engine>* ptr = new WeakPtr<Engine>(spaceship->getEngine());
189                    new Timer(10, false, &createExecutor(createFunctor(&Dynamicmatch::resetSpeedFactor, this))->setDefaultValue(0, ptr), true);
190                }
191
192            }
193            // killer vs piggy
194            else if (source==killer &&target==piggy)            //party and colour switch       
195            {
196            playerParty_[victim->getPlayer()]=killer;
197            playerParty_[originator->getPlayer()]=piggy;
198
199            setPlayerColour(victim->getPlayer());               //victim colour
200            setPlayerColour(originator->getPlayer());           //originator colour
201            }
202            //Case: friendly fire
203            else if (friendlyfire && (source == target))
204            {
205                std::map<PlayerInfo*, Player>::iterator it = this->players_.find(originator->getPlayer());
206                if (it != this->players_.end())
207                    {
208                        it->second.frags_--;
209                    }
210            }
211        }// from far far away not to be removed!
212        return false; //default: no damage
213    }
214
215
216
217    bool Dynamicmatch::allowPawnDeath(Pawn* victim, Pawn* originator)
218    {   
219        //killers can kill chasers and killers can be killed by chasers
220        if ((playerParty_[originator->getPlayer()] == killer && playerParty_[victim->getPlayer()] == chaser)||(playerParty_[victim->getPlayer()] == killer &&
221        playerParty_[originator->getPlayer()] == chaser ))
222        {
223            if (playerParty_[originator->getPlayer()] == killer)        //reward the killer
224            {
225                std::map<PlayerInfo*, Player>::iterator it = this->players_.find(originator->getPlayer());
226                if (it != this->players_.end())
227                {
228                    it->second.frags_+=20;      //value must be tested
229                }
230            }
231        return true;
232        }
233        else return false;
234    }
235   
236    void Dynamicmatch::playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn) //set party + colouring
237    {
238        if (!player)
239            return;
240       
241        Dynamicmatch::setPlayerColour(player);  //Set playercolour
242        evaluatePlayerParties();
243    }
244
245    void Dynamicmatch::playerEntered(PlayerInfo* player) //standardfunction
246    {
247        if (!player)// only for safety
248            return;
249        playerParty_[player]=chaser;            //Set playerparty
250        numberOf[chaser]++;
251        Gametype::playerEntered(player);
252        const std::string& message6 = player->getName() + " entered the game";
253        COUT(0) << message6 << std::endl;
254        Host::Broadcast(message6);
255    }
256
257    bool Dynamicmatch::playerLeft(PlayerInfo* player) //standardfunction
258    {
259        bool valid_player = Gametype::playerLeft(player);
260        if (valid_player)
261        {
262            switch (playerParty_[player])
263            {
264            case 0: numberOf[chaser]--; break;
265            case 1: numberOf[piggy]--; break;
266            case 2: numberOf[killer]--; break;
267            }
268            const std::string& message = player->getName() + " left the game";
269            COUT(0) << message << std::endl;
270            Host::Broadcast(message);
271                //remove player from map
272            playerParty_.erase (player);
273                //adjust player parties
274            evaluatePlayerParties();
275        }
276
277        return valid_player;
278    }
279
280
281    void Dynamicmatch::tick(float dt)
282    {
283        SUPER(Dynamicmatch, tick, dt);
284
285        if (this->hasStarted() && !gameEnded_)
286        {   pointsPerTime =pointsPerTime + dt;
287            gameTime_ = gameTime_ - dt;
288            if (pointsPerTime > 5)
289            {
290                pointsPerTime=0.0f;
291               
292            }
293            if (gameTime_<= 0)
294            {
295                this->gameEnded_ = true;
296                this->end();       
297            }
298            if ( gameTime_ <= timesequence_ && gameTime_ > 0)
299            {
300                const std::string& message = multi_cast<std::string>(timesequence_) + " seconds left!";
301
302                this->gtinfo_->sendAnnounceMessage(message);
303
304                if (timesequence_ >= 30 && timesequence_ <= 60)
305                {
306                    timesequence_ = timesequence_ - 10;
307                }
308                else if (timesequence_ <= 30)
309                {
310                    timesequence_ = timesequence_ - 5;
311                }
312                else
313                {
314                    timesequence_ = timesequence_ - 30;
315                }
316            }
317        }
318    }
319
320    void Dynamicmatch::rewardPig()
321    {
322        //durch alle Spieler iterieren
323        /*std::string message("Game started!");
324            COUT(0) << message << std::endl;
325            Host::Broadcast(message);*/
326        // allen Spielern mit der Pig-party frags++
327        ;
328    }
329    void Dynamicmatch::setPlayerColour(PlayerInfo* player) // sets a players colour
330    {
331        std::map<PlayerInfo*, int>::const_iterator it_player = this->playerParty_.find(player);
332        Pawn* pawn = dynamic_cast<Pawn*>(player->getControllableEntity());
333            if (pawn)
334            {
335                pawn->setRadarObjectColour(this->partyColours_[it_player->second]); //does this work? //what about playerParty_[it_player] instead of it_player->second
336
337                std::set<WorldEntity*> pawnAttachments = pawn->getAttachedObjects();
338                for (std::set<WorldEntity*>::iterator it = pawnAttachments.begin(); it != pawnAttachments.end(); ++it)
339                {
340                    if ((*it)->isA(Class(TeamColourable)))
341                    {
342                        TeamColourable* tc = orxonox_cast<TeamColourable*>(*it);
343                        tc->setTeamColour(this->partyColours_[it_player->second]);
344                    }
345                }
346            }
347        }
348
349    void Dynamicmatch::evaluatePlayerParties() //manages the notEnough booleans (here the percentage of special players is implemented)
350    {
351        //pigs: 1 + every 6th player is a pig
352        if ( (1+this->getNumberOfPlayers()/6) > numberOf[piggy]) {notEnoughPigs=true;}
353        else {notEnoughPigs=false;}
354        //killers: every 4th player is a killer
355        if (getNumberOfPlayers()/4 > numberOf[killer]) {notEnoughKillers=true;}
356        else {notEnoughKillers=false;}
357        //chasers: there are more chasers than killers + pigs
358        if (numberOf[piggy]+numberOf[killer] > numberOf[chaser]) {notEnoughChasers=true;}
359        else {notEnoughChasers=false;} 
360    }
361
362    int Dynamicmatch::getParty(PlayerInfo* player) // helper function for ArtificialController
363    {
364        return this->playerParty_[player];
365    }
366
367    void Dynamicmatch::resetSpeedFactor(WeakPtr<Engine>* ptr)// helper function
368    {
369        if (*ptr)
370        {
371            (*ptr)->setSpeedFactor(1.0f);
372        }
373        delete ptr;
374    }
375
376    bool Dynamicmatch::playerChangedName(PlayerInfo* player) //standardfunction
377    {
378        bool valid_player = Gametype::playerChangedName(player);
379        if (valid_player)
380        {
381            const std::string& message = player->getOldName() + " changed name to " + player->getName();
382            COUT(0) << message << std::endl;
383            Host::Broadcast(message);
384        }
385
386        return valid_player;
387    }
388
389    void Dynamicmatch::start() 
390    {   
391        Gametype::start();
392        if(!tutorial)
393        {
394            std::string message("Game started!");
395            COUT(0) << message << std::endl;
396            Host::Broadcast(message);
397        }
398        else if(tutorial) //in order to explain how this gametype works briefly
399        {
400            std::string tutotrialmessage("Shoot at other players as long as every player is red.\n\nIf you are fast enough you're spaceship will become green.\n\nIf you are hit you'll become blue.");
401            COUT(0) << tutotrialmessage << std::endl;
402            Host::Broadcast(tutotrialmessage);
403            callInstructions_.setTimer(10, false, createExecutor(createFunctor(&Dynamicmatch::instructions, this)));
404        }
405    }   
406
407    void Dynamicmatch::instructions()
408    {
409        std::string message("Earn points:\n\n\n\tIf you're red: Chase the blue player!\n\n\tIf you're blue shoot at a red player or hide.\n\n\tIf you're green: You've got the licence to kill red players!");
410        COUT(0) << message << std::endl;
411        Host::Broadcast(message);
412        callInstructions_.setTimer(10, false, createExecutor(createFunctor(&Dynamicmatch::furtherInstructions, this)));
413    }
414
415    void Dynamicmatch::furtherInstructions()
416    {
417        std::string message("After 3 Minutes the game is over.");
418        COUT(0) << message << std::endl;
419        Host::Broadcast(message);
420    }
421    void Dynamicmatch::end()
422    {
423        Gametype::end();
424
425        std::string message("Time out. Press F2 to see the points you scored.");
426        COUT(0) << message << std::endl;
427        Host::Broadcast(message);
428        /*for (std::map<PlayerInfo*, int>::iterator it = this->playerParty_.begin(); it != this->playerParty_.end(); ++it)
429                {
430                    if (it->first->getClientID() == CLIENTID_UNKNOWN)
431                        continue;
432
433                    if (it->second == 1)
434                        this->gtinfo_->sendAnnounceMessage("You have won the match!", it->first->getClientID());
435                    else
436                        this->gtinfo_->sendAnnounceMessage("You have lost the match!", it->first->getClientID());
437                }*/
438    }
439    SpawnPoint* Dynamicmatch::getBestSpawnPoint(PlayerInfo* player) const
440    {
441        int desiredTeamNr = -1;
442        std::map<PlayerInfo*, int>::const_iterator it_player = this->playerParty_.find(player);
443        if (it_player != this->playerParty_.end())
444            desiredTeamNr = it_player->second;
445
446        // Only use spawnpoints of the own team (or non-team-spawnpoints)
447        std::set<SpawnPoint*> teamSpawnPoints = this->spawnpoints_;
448        for (std::set<SpawnPoint*>::iterator it = teamSpawnPoints.begin(); it != teamSpawnPoints.end(); )
449        {
450            if ((*it)->isA(Class(TeamSpawnPoint)))
451            {
452                TeamSpawnPoint* tsp = orxonox_cast<TeamSpawnPoint*>(*it);
453                if (tsp && static_cast<int>(tsp->getTeamNumber()) != desiredTeamNr)//getTeamNumber!!
454                {
455                    teamSpawnPoints.erase(it++);
456                    continue;
457                }
458            }
459
460            ++it;
461        }
462
463        if (teamSpawnPoints.size() > 0)
464        {
465            unsigned int randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(teamSpawnPoints.size())));
466            unsigned int index = 0;
467            for (std::set<SpawnPoint*>::const_iterator it = teamSpawnPoints.begin(); it != teamSpawnPoints.end(); ++it)
468            {
469                if (index == randomspawn)
470                    return (*it);
471
472                ++index;
473            }
474        }
475
476        return 0;
477    }
478
479}
Note: See TracBrowser for help on using the repository browser.