Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/lastmanstanding2/src/orxonox/gametypes/LastTeamStanding.cc @ 7697

Last change on this file since 7697 was 7697, checked in by dafrick, 14 years ago

Manually merging changes in lastmanstanding branch to lastmanstanding2 branch.
Please continue here, since the lastmanstanding branch has already been merged.

File size: 10.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 *      Johannes Ritz
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "LastTeamStanding.h"
30
31#include "core/CoreIncludes.h"
32#include "network/Host.h"
33#include "infos/PlayerInfo.h"
34#include "worldentities/pawns/Pawn.h"
35#include "core/ConfigValueIncludes.h"
36#include "util/Convert.h"
37//TODO: teamsAlive instead of playersAlive
38
39namespace orxonox
40{
41    CreateUnloadableFactory(LastTeamStanding);
42
43    LastTeamStanding::LastTeamStanding(BaseObject* creator) : TeamDeathmatch(creator)
44    {
45        RegisterObject(LastTeamStanding);
46        this->bForceSpawn_=true;
47        this->lives=4;
48        this->teamsAlive=0;
49        this->timeRemaining=15.0f;
50        this->respawnDelay=4.0f;
51        this->bNoPunishment=false;
52        this->bHardPunishment=false;
53        this->punishDamageRate=0.4f;
54        this->setHUDTemplate("LastTeamStandingHUD");
55        this->eachTeamsPlayers = new int[teams_];
56    }
57   
58    void LastTeamStanding::~LastTeamStanding()
59    {
60        delete[] this->eachTeamsPlayers;
61    }   
62
63    void LastTeamStanding::spawnDeadPlayersIfRequested()
64    {
65        for (std::map<PlayerInfo*, Player>::iterator it = this->players_.begin(); it != this->players_.end(); ++it)
66            if (it->second.state_ == PlayerState::Dead)
67            {
68                bool alive = (0<playerLives_[it->first]&&(inGame_[it->first]));
69                if (alive&&(it->first->isReadyToSpawn() || this->bForceSpawn_))
70                {
71                    this->spawnPlayer(it->first);
72                }
73            }
74    }
75
76
77    void LastTeamStanding::setConfigValues()
78    {
79        SetConfigValue(lives, 4);
80        SetConfigValue(timeRemaining, 15.0f);
81        SetConfigValue(respawnDelay, 4.0f);
82        SetConfigValue(bNoPunishment, false);
83        SetConfigValue(bHardPunishment, false);
84    }
85
86    bool LastTeamStanding::allowPawnDamage(Pawn* victim, Pawn* originator)
87    {
88        bool allow = TeamDeathmatch::allowPawnDamage(victim, originator);
89        if(!allow) {return allow;}
90        if (originator && originator->getPlayer())// only for safety
91        {
92            this->timeToAct_[originator->getPlayer()]=timeRemaining;
93
94            std::map<PlayerInfo*, Player>::iterator it = this->players_.find(originator->getPlayer());
95            if (it != this->players_.end())
96            {
97                if (it->first->getClientID()== CLIENTID_UNKNOWN)
98                    return true;
99                const std::string& message = ""; // resets Camper-Warning-message
100                this->gtinfo_->sendFadingMessage(message,it->first->getClientID());
101            }   
102        }
103        return allow;
104    }
105
106    bool LastTeamStanding::allowPawnDeath(Pawn* victim, Pawn* originator)
107    {
108        if (!victim||!victim->getPlayer())// only for safety
109            return true;
110        bool allow =TeamDeathmatch::allowPawnDeath(victim, originator);
111        if(!allow) {return allow;}
112        playerLives_[victim->getPlayer()]=playerLives_[victim->getPlayer()]-1;
113        this->inGame_[victim->getPlayer()]=false;//if player dies he, isn't allowed to respawn immediately
114        if (playerLives_[victim->getPlayer()]<=0)//if player lost all lives
115        {
116            this->eachTeamsPlayers[getTeam(victim->getPlayer())]--;
117            if(eachTeamsPlayers[getTeam(victim->getPlayer())]==0)//last team member died
118                this->teamsAlive--;
119            const std::string& message = victim->getPlayer()->getName() + " has lost all lives";
120            COUT(0) << message << std::endl;
121            Host::Broadcast(message);
122        }
123
124        return allow;
125    }
126
127    int LastTeamStanding::getMinLives()
128    {
129        int min=lives;
130        for (std::map<PlayerInfo*, int>::iterator it = this->playerLives_.begin(); it != this->playerLives_.end(); ++it)
131        {
132            if (it->second<=0)
133                continue;
134            if (it->second<lives)
135                min=it->second;
136        }
137        return min;
138    }
139
140    void LastTeamStanding::end()
141    {
142        Gametype::end();
143       
144        for (std::map<PlayerInfo*, int>::iterator it = this->playerLives_.begin(); it != this->playerLives_.end(); ++it)
145        {
146            if (it->first->getClientID() == CLIENTID_UNKNOWN)
147                continue;
148
149            if (it->second > 0)
150                this->gtinfo_->sendAnnounceMessage("You have won the match!", it->first->getClientID());
151            else
152                this->gtinfo_->sendAnnounceMessage("You have lost the match!", it->first->getClientID());
153        }
154    }
155
156    int LastTeamStanding::playerGetLives(PlayerInfo* player)
157    {
158        if (player)
159            return  playerLives_[player];
160        else
161            return 0;
162    }
163   
164    int LastTeamStanding::getNumTeamsAlive() const
165    {
166        return this->teamsAlive;
167    }
168
169    void LastTeamStanding::playerEntered(PlayerInfo* player)
170    {
171        if (!player)// only for safety
172            return;
173        Deathmatch::playerEntered(player);
174        if (teamsAlive<=1)
175            playerLives_[player]=lives;
176        else
177            playerLives_[player]=getMinLives();//new players only get minimum of lives
178           
179        if(this->eachTeamsPlayers[getTeam(player)]==0)
180            this->teamsAlive++;
181        this->eachTeamsPlayers[getTeam(player)]++;
182       
183        this->timeToAct_[player]=timeRemaining;
184        this->playerDelayTime_[player]=respawnDelay;
185        this->inGame_[player]=true;
186    }
187
188    bool LastTeamStanding::playerLeft(PlayerInfo* player)
189    {
190        bool valid_player = Deathmatch::playerLeft(player);
191        if (valid_player)
192        {
193            this->eachTeamsPlayers[getTeam(player)]--;
194            if(this->eachTeamsPlayers[getTeam(player)]==0)
195                 this->teamsAlive--;
196            this->playerLives_.erase (player);
197            this->playerDelayTime_.erase (player);
198            this->inGame_.erase (player);
199            this->timeToAct_.erase(player);
200        }
201
202        return valid_player;
203    }
204
205    void LastTeamStanding::playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn)
206    {
207        if (!player)
208            return;
209        TeamDeathmatch::playerStartsControllingPawn(player,pawn);
210       
211        this->timeToAct_[player]=timeRemaining+3.0f+respawnDelay;//reset timer
212        this->playerDelayTime_[player]=respawnDelay;
213       
214        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
215        if (it != this->players_.end())
216        {
217            if (it->first->getClientID()== CLIENTID_UNKNOWN)
218                return;
219            const std::string& message = ""; // resets Camper-Warning-message
220            this->gtinfo_->sendFadingMessage(message,it->first->getClientID());
221        } 
222    }
223
224    void LastTeamStanding::punishPlayer(PlayerInfo* player)
225    {
226        if(!player)
227            return;
228        if(bNoPunishment)
229            return;
230        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
231        if (it != this->players_.end())
232        {
233            if(!player->getControllableEntity())
234                return;
235            Pawn* pawn = dynamic_cast<Pawn*>(player->getControllableEntity());
236            if(!pawn)
237                return;
238            if(bHardPunishment)
239            {
240                pawn->kill();
241                this->timeToAct_[player]=timeRemaining+3.0f+respawnDelay;//reset timer
242            }
243            else
244            {
245                float damage=pawn->getMaxHealth()*punishDamageRate*0.5;//TODO: Factor 0.5 is hard coded. Where is the ratio between MaxHealth actually defined?
246                pawn->removeHealth(damage);
247                this->timeToAct_[player]=timeRemaining;//reset timer
248            }
249        }
250    }
251
252    void LastTeamStanding::tick(float dt)
253    {
254        SUPER(LastTeamStanding, tick, dt);
255        if(this->hasStarted()&&(!this->hasEnded()))
256        {
257            if ((this->hasStarted()&&(teamsAlive<=1)))//last team remaining
258            {
259                this->end();
260            }
261            for (std::map<PlayerInfo*, float>::iterator it = this->timeToAct_.begin(); it != this->timeToAct_.end(); ++it)
262            {   
263                if (playerGetLives(it->first)<=0)//Players without lives shouldn't be affected by time.
264                    continue;     
265                it->second-=dt;//Decreases punishment time.
266                if (!inGame_[it->first])//Manages respawn delay - player is forced to respawn after the delaytime is used up.
267                {
268                    playerDelayTime_[it->first]-=dt;
269                    if (playerDelayTime_[it->first]<=0)
270                    this->inGame_[it->first]=true;
271
272                    if (it->first->getClientID()== CLIENTID_UNKNOWN)
273                        continue;
274                    int output=1+playerDelayTime_[it->first];
275                    const std::string& message = "Respawn in " +multi_cast<std::string>(output)+ " seconds." ;//Countdown
276                    this->gtinfo_->sendFadingMessage(message,it->first->getClientID());
277                }
278                else if (it->second<0.0f)
279                {
280                    it->second=timeRemaining+3.0f;//reset punishment-timer
281                    if (playerGetLives(it->first)>0)
282                    {
283                        this->punishPlayer(it->first);
284                        if (it->first->getClientID()== CLIENTID_UNKNOWN)
285                            return;
286                        const std::string& message = ""; // resets Camper-Warning-message
287                        this->gtinfo_->sendFadingMessage(message,it->first->getClientID());
288                    }
289                }
290                else if (it->second<timeRemaining/5)//Warning message
291                {
292                    if (it->first->getClientID()== CLIENTID_UNKNOWN)
293                        continue;
294                    const std::string& message = "Camper Warning! Don't forget to shoot.";
295                    this->gtinfo_->sendFadingMessage(message,it->first->getClientID());
296                }
297            }
298        }
299    }
300
301}
Note: See TracBrowser for help on using the repository browser.