Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/gametypes/LastTeamStanding.cc @ 8178

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

Merged lastmastanding3 into trunk. There's an xml parsing error that only appeared after merging. The level seems to load properly though.

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