Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation/src/orxonox/gametypes/LastTeamStanding.cc @ 8612

Last change on this file since 8612 was 8612, checked in by landauf, 13 years ago

fixed possible bug in LastTeamStanding

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