Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7901 was 7901, checked in by jo, 13 years ago

Finally working as intended.

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