Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/lastmanstanding3/src/orxonox/gametypes/LastTeamStanding.cc @ 8175

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

test.

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.