Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/output/src/orxonox/gametypes/LastTeamStanding.cc @ 8829

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

enhanced chat system. chat related code is now separated into network-side code (located in Host, Client, Server) and client-side code (located in ChatManager).
note that there are now two chat related listeners: NetworkChatListener, which is used to send chat from the network to ChatManager, and ChatListener, which is used to send online and offline chat from ChatManager to the actual chat interfaces (ChatOverlay, ChatInputHandler, …).
the "chat" console command now supports a second argument which is the clientID of the receiver. this allows private messages (or gameplay messages directed to only one specific player).

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