Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

adding 3rd party: killers, making the gametype playable for larger groups of players, bug removed

  • Property svn:eol-style set to native
File size: 18.6 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
59namespace orxonox
60{
61    CreateUnloadableFactory(Dynamicmatch);
62
63    Dynamicmatch::Dynamicmatch(BaseObject* creator) : Gametype(creator)
64    {
65        RegisterObject(Dynamicmatch);
66        this->gameTime_ = 180;
67        this->setConfigValues();
68        this->chaser=0;
69        this->piggy=1;
70        this->killer=2;
71        this->notEnoughPigs=false;
72        this->notEnoughKillers=false;
73        this->notEnoughChasers=false;
74        this->gameEnded_ =false;
75        this->timesequence_ = static_cast<int>(this->gameTime_);
76        this->friendlyfire=true;
77        this->numberOf[chaser]=0;
78        this->numberOf[piggy]=0;
79        this->numberOf[killer]=0;
80        this->tutorial=true;
81        this->pointsPerTime=0.0f;
82    }
83
84    void Dynamicmatch::setConfigValues()
85    {
86        SetConfigValue(gameTime_, 180);
87        SetConfigValue(friendlyfire, true);
88        SetConfigValue(tutorial, true);
89        static ColourValue colours[] =
90        {
91            ColourValue(0.3f, 0.3f, 1.0f),      //chasercolour
92            ColourValue(1.0f, 0.3f, 0.3f),      //piggycolour
93            ColourValue(0.3f, 1.0f, 0.3f)       //killercolour  what about black: 0.0f, 0.0f, 0.0f
94           
95        };
96        static std::vector<ColourValue> defaultcolours(colours, colours + sizeof(colours) / sizeof(ColourValue));
97
98        SetConfigValue(partyColours_, defaultcolours);
99    }
100
101    bool Dynamicmatch::allowPawnDamage(Pawn* victim, Pawn* originator)//tested - works fine
102    {   
103        if (!originator||!victim)
104        {return false;}
105        if (victim && victim->getPlayer()) //&& originator && originator->getPlayer() ??
106        {
107        int target= playerParty_[victim->getPlayer()];
108        int source= playerParty_[originator->getPlayer()];
109
110            //Case: Not Enough Pigs: party change (= party management)
111            if (notEnoughPigs)
112            {
113                       
114                numberOf[target]--;                             //decrease numberof victims's party
115                const std::string& message = std::string(" Chasers ") + multi_cast<std::string>(numberOf[chaser]); COUT(0) << message << std::endl; Host::Broadcast(message);
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                const std::string& message1 = std::string(" Pig") + multi_cast<std::string>(numberOf[piggy]); COUT(0) << message1 << std::endl; Host::Broadcast(message1);
120                    if (notEnoughKillers)                       //reward the originator
121                    {
122                        numberOf[source]--;                     //decrease numberof originator's party
123                        const std::string& message = std::string(" Chasers ") + multi_cast<std::string>(numberOf[chaser]); COUT(0) << message << std::endl; Host::Broadcast(message);
124                        playerParty_[originator->getPlayer()]=killer;           //originator's new party: killer
125                        setPlayerColour(originator->getPlayer());               //originator's new colour
126                        numberOf[killer]++;
127                        const std::string& message2 = std::string(" Killers ") + multi_cast<std::string>(numberOf[killer]); COUT(0) << message2 << std::endl; Host::Broadcast(message2);
128                    }
129                evaluatePlayerParties();                        //check if the party change has to trigger futher party changes
130                       
131                //Give new pig boost
132                SpaceShip* spaceship = dynamic_cast<SpaceShip*>(victim);
133                if (spaceship && spaceship->getEngine())
134                {
135                    spaceship->getEngine()->setSpeedFactor(5);
136                    WeakPtr<Engine>* ptr = new WeakPtr<Engine>(spaceship->getEngine());
137                    new Timer(10, false, &createExecutor(createFunctor(&Dynamicmatch::resetSpeedFactor, this))->setDefaultValue(0, ptr), true);
138                }
139                std::string message5("First victim.");// for testing purposes
140                COUT(0) << message5 << std::endl;
141                Host::Broadcast(message5);
142            }
143
144            //Case: notEnoughKillers: party change
145            else if (notEnoughKillers)
146            {
147                numberOf[target]--;     //decrease numberof victims's party
148                playerParty_[victim->getPlayer()]=killer;       //victim's new party: killer
149                setPlayerColour(victim->getPlayer());           //victim colour
150                numberOf[killer]++;                             //party switch: number of players is not affected (decrease and increase)
151                const std::string& message = std::string(" Killers ") + multi_cast<std::string>(numberOf[killer]); COUT(0) << message << std::endl; Host::Broadcast(message);
152                evaluatePlayerParties();                        //check if the party change has to trigger futher party changes
153            }
154            //Case: notEnoughChasers: party change
155            else if (notEnoughChasers)
156            {
157                numberOf[target]--;     //decrease numberof victims's party
158                playerParty_[victim->getPlayer()]=chaser;       //victim's new party: chaser
159                setPlayerColour(victim->getPlayer());           //victim colour
160                numberOf[chaser]++;                             //party switch: number of players is not affected (decrease and increase)
161                const std::string& message = std::string(" Chasers ") + multi_cast<std::string>(numberOf[chaser]); COUT(0) << message << std::endl; Host::Broadcast(message);
162                evaluatePlayerParties();                        //check if the party change has to trigger futher party changes
163            }
164
165            //Case: chaser vs. killer
166            else if ((source == killer && target == chaser)||(target == killer && source == chaser ))
167            {
168                return true;
169            }
170
171            //Case: a chaser hits piggy
172            else if ((source==chaser)&&(target==piggy))
173            {
174                std::map<PlayerInfo*, Player>::iterator it = this->players_.find(originator->getPlayer());
175                if (it != this->players_.end())
176                    {
177                        it->second.frags_++;
178                    }
179            }
180            //Case: piggy hits chaser
181            else if (source==piggy&&target==chaser)
182            {
183                //partyswitch: victim bcomes piggy and the originator(piggy) becomes chaser
184                playerParty_[victim->getPlayer()]=piggy;
185                playerParty_[originator->getPlayer()]=chaser;
186                //announce
187                const std::string& messageVictim = victim->getPlayer()->getName() + " is victim";
188                COUT(0) << messageVictim << std::endl;
189                Host::Broadcast(messageVictim);
190
191                //party switch -> colour switch         
192                setPlayerColour(victim->getPlayer()); //victim colour
193                setPlayerColour(originator->getPlayer());//originator colour
194
195                //Give new pig boost
196                SpaceShip* spaceship = dynamic_cast<SpaceShip*>(victim);
197                if (spaceship && spaceship->getEngine())
198                {
199                    spaceship->getEngine()->setSpeedFactor(5);
200                    WeakPtr<Engine>* ptr = new WeakPtr<Engine>(spaceship->getEngine());
201                    new Timer(10, false, &createExecutor(createFunctor(&Dynamicmatch::resetSpeedFactor, this))->setDefaultValue(0, ptr), true);
202                }
203
204            }
205            //TODO: killer vs piggy
206            else if (source==killer &&target==piggy)            //party and colour switch       
207            {
208            playerParty_[victim->getPlayer()]=killer;
209            playerParty_[originator->getPlayer()]=piggy;
210
211            setPlayerColour(victim->getPlayer());               //victim colour
212            setPlayerColour(originator->getPlayer());           //originator colour
213            }
214            //Case: friendly fire
215            else if (friendlyfire && (source == target))
216            {
217                std::map<PlayerInfo*, Player>::iterator it = this->players_.find(originator->getPlayer());
218                if (it != this->players_.end())
219                    {
220                        it->second.frags_--;
221                    }
222            }
223        }// from far far away not to be removed!
224        return false; //default: no damage
225    }
226
227
228
229    bool Dynamicmatch::allowPawnDeath(Pawn* victim, Pawn* originator)
230    {   
231        //killers can kill chasers and killers can be killed by chasers
232        if ((playerParty_[originator->getPlayer()] == killer && playerParty_[victim->getPlayer()] == chaser)||(playerParty_[victim->getPlayer()] == killer &&
233        playerParty_[originator->getPlayer()] == chaser ))
234        {
235            if (playerParty_[originator->getPlayer()] == killer)        //reward the killer
236            {
237                std::map<PlayerInfo*, Player>::iterator it = this->players_.find(originator->getPlayer());
238                if (it != this->players_.end())
239                {
240                    it->second.frags_+=20;      //value must be tested
241                }
242            }
243        return true;
244        }
245        else return false;
246    }
247   
248    void Dynamicmatch::playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn) //set party + colouring
249    {
250        if (!player)
251            return;
252       
253        Dynamicmatch::setPlayerColour(player);  //Set playercolour
254        evaluatePlayerParties();
255    }
256
257    void Dynamicmatch::playerEntered(PlayerInfo* player) //standardfunction
258    {
259        if (!player)// only for safety
260            return;
261        playerParty_[player]=chaser;            //Set playerparty
262        numberOf[chaser]++; const std::string& message = std::string(" Chasers ") + multi_cast<std::string>(numberOf[chaser]); COUT(0) << message << std::endl; Host::Broadcast(message);
263        Gametype::playerEntered(player);
264        const std::string& message6 = player->getName() + " entered the game";
265        COUT(0) << message6 << std::endl;
266        Host::Broadcast(message6);
267    }
268
269    bool Dynamicmatch::playerLeft(PlayerInfo* player) //standardfunction
270    {
271        bool valid_player = Gametype::playerLeft(player);
272        if (valid_player)
273        {
274            switch (playerParty_[player])
275            {
276            case 0: numberOf[chaser]--; break;
277            case 1: numberOf[piggy]--; break;
278            case 2: numberOf[killer]--; break;
279            }
280            const std::string& message = player->getName() + " left the game";
281            COUT(0) << message << std::endl;
282            Host::Broadcast(message);
283                //remove player from map
284            playerParty_.erase (player);
285                //adjust player parties
286            evaluatePlayerParties();
287        }
288
289        return valid_player;
290    }
291
292   
293
294   
295
296    void Dynamicmatch::tick(float dt)
297    {
298        SUPER(Dynamicmatch, tick, dt);//TODO - was bedeutet diese Zeile
299
300        if (this->hasStarted() && !gameEnded_)
301        {   pointsPerTime =pointsPerTime + dt;
302            gameTime_ = gameTime_ - dt;
303            if (pointsPerTime > 5)
304            {
305                pointsPerTime=0.0f;
306               
307            }
308            if (gameTime_<= 0)
309            {
310                this->gameEnded_ = true;
311                this->end();       
312            }
313            if ( gameTime_ <= timesequence_ && gameTime_ > 0)
314            {
315                const std::string& message = multi_cast<std::string>(timesequence_) + " seconds left!";
316
317                this->gtinfo_->sendAnnounceMessage(message);
318
319                if (timesequence_ >= 30 && timesequence_ <= 60)
320                {
321                    timesequence_ = timesequence_ - 10;
322                }
323                else if (timesequence_ <= 30)
324                {
325                    timesequence_ = timesequence_ - 5;
326                }
327                else
328                {
329                    timesequence_ = timesequence_ - 30;
330                }
331            }
332        }
333    }
334
335    void Dynamicmatch::rewardPig()
336    {
337        //durch alle Spieler iterieren
338        // allen Spielern mit der Pig-party frags++
339        ;
340    }
341    void Dynamicmatch::setPlayerColour(PlayerInfo* player) // sets a players colour
342    {
343        std::map<PlayerInfo*, int>::const_iterator it_player = this->playerParty_.find(player);
344        Pawn* pawn = dynamic_cast<Pawn*>(player->getControllableEntity());
345            if (pawn)
346            {
347                pawn->setRadarObjectColour(this->partyColours_[it_player->second]); //does this work? //what about playerParty_[it_player] instead of it_player->second
348
349                std::set<WorldEntity*> pawnAttachments = pawn->getAttachedObjects();
350                for (std::set<WorldEntity*>::iterator it = pawnAttachments.begin(); it != pawnAttachments.end(); ++it)
351                {
352                    if ((*it)->isA(Class(TeamColourable)))
353                    {
354                        TeamColourable* tc = orxonox_cast<TeamColourable*>(*it);
355                        tc->setTeamColour(this->partyColours_[it_player->second]);
356                    }
357                }
358            }
359        }
360
361    void Dynamicmatch::evaluatePlayerParties() //manages the notEnough booleans (here the percentage of special players is implemented)
362    {
363        //pigs: 1 + every 6th player is a pig
364        if ( (1+this->getNumberOfPlayers()/6) > numberOf[piggy]) {notEnoughPigs=true;}
365        else {notEnoughPigs=false;}
366        //killers: every 4th player is a killer
367        if (getNumberOfPlayers()/4 > numberOf[killer]) {notEnoughKillers=true;}
368        else {notEnoughKillers=false;}
369        //chasers: there are more chasers than killers + pigs
370        if (numberOf[piggy]+numberOf[killer] > numberOf[chaser]) {notEnoughChasers=true;}
371        else {notEnoughChasers=false; const std::string& message = "Players Evaluated";COUT(0) << message << std::endl; Host::Broadcast(message);}
372        const std::string& messagetest = multi_cast<std::string>(numberOf[piggy]+numberOf[chaser]+numberOf[killer]) + "   players!";
373        COUT(0) << messagetest << std::endl; Host::Broadcast(messagetest);     
374    }
375
376    int Dynamicmatch::getParty(PlayerInfo* player) // helper function for ArtificialController
377    {
378        return this->playerParty_[player];
379    }
380
381    void Dynamicmatch::resetSpeedFactor(WeakPtr<Engine>* ptr)// helper function
382    {
383        if (*ptr)
384        {
385            (*ptr)->setSpeedFactor(1.0f);
386        }
387        delete ptr;
388    }
389
390    bool Dynamicmatch::playerChangedName(PlayerInfo* player) //standardfunction
391    {
392        bool valid_player = Gametype::playerChangedName(player);
393        if (valid_player)
394        {
395            const std::string& message = player->getOldName() + " changed name to " + player->getName();
396            COUT(0) << message << std::endl;
397            Host::Broadcast(message);
398        }
399
400        return valid_player;
401    }
402
403    void Dynamicmatch::start() 
404    {   
405        Gametype::start();
406        if(!tutorial)
407        {
408            std::string message("Game started!");
409            COUT(0) << message << std::endl;
410            Host::Broadcast(message);
411        }
412        else if(tutorial) //in order to explain how this gametype works briefly
413        {
414            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.");
415            COUT(0) << tutotrialmessage << std::endl;
416            Host::Broadcast(tutotrialmessage);
417            callInstructions_.setTimer(10, false, createExecutor(createFunctor(&Dynamicmatch::instructions, this)));
418        }
419    }   
420
421    void Dynamicmatch::instructions()
422    {
423        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!");
424        COUT(0) << message << std::endl;
425        Host::Broadcast(message);
426        callInstructions_.setTimer(10, false, createExecutor(createFunctor(&Dynamicmatch::furtherInstructions, this)));
427    }
428
429    void Dynamicmatch::furtherInstructions()
430    {
431        std::string message("After 3 Minutes the game is over.");
432        COUT(0) << message << std::endl;
433        Host::Broadcast(message);
434    }
435    void Dynamicmatch::end()
436    {
437        Gametype::end();
438
439        std::string message("Time out. Press F2 to see the points you scored.");
440        COUT(0) << message << std::endl;
441        Host::Broadcast(message);
442        /*for (std::map<PlayerInfo*, int>::iterator it = this->teamnumbers_.begin(); it != this->teamnumbers_.end(); ++it)
443                {
444                    if (it->first->getClientID() == CLIENTID_UNKNOWN)
445                        continue;
446
447                    if (it->second == 1)
448                        this->gtinfo_->sendAnnounceMessage("You have won the match!", it->first->getClientID());
449                    else
450                        this->gtinfo_->sendAnnounceMessage("You have lost the match!", it->first->getClientID());
451                }*/
452    }
453
454}
Note: See TracBrowser for help on using the repository browser.