Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/util/multiplayer_team_deathmatch.cc @ 8076

Last change on this file since 8076 was 8068, checked in by patrick, 18 years ago

trunk: merged the network branche back to trunk

File size: 7.8 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11### File Specific:
12   main-programmer: Patrick Boenzli
13*/
14
15#define DEBUG_MODULE_GAME_RULES
16
17#include <map>
18
19#include "multiplayer_team_deathmatch.h"
20
21#include "util/loading/load_param.h"
22#include "util/loading/factory.h"
23
24#include "render2D/image_plane.h"
25#include "state.h"
26#include "class_list.h"
27
28#include "player.h"
29#include "playable.h"
30#include "space_ships/space_ship.h"
31
32
33#include "shared_network_data.h"
34#include "terrain.h"
35#include "class_list.h"
36#include "space_ships/space_ship.h"
37
38#include "network_game_manager.h"
39
40
41using namespace std;
42
43
44CREATE_FACTORY(MultiplayerTeamDeathmatch, CL_MULTIPLAYER_TEAM_DEATHMATCH);
45
46
47/**
48 * constructor
49 */
50MultiplayerTeamDeathmatch::MultiplayerTeamDeathmatch(const TiXmlElement* root)
51  : NetworkGameRules(root)
52{
53  this->setClassID(CL_MULTIPLAYER_TEAM_DEATHMATCH, "MultiplayerTeamDeathmatch");
54
55  this->bLocalPlayerDead = false;
56  this->deathTimeout = 10.0f;     // 5 seconds
57  this->timeout = 0.0f;
58  this->numTeams = 2;
59  this->currentGameState = GAMESTATE_PRE_GAME;
60  this->gameStateTimer = 10.0f;
61
62  this->deathScreen = new ImagePlane();
63  this->deathScreen->setSize(State::getResX()/4.0, State::getResY()/4.0);
64  this->deathScreen->setAbsCoor2D(State::getResX()/2.0f, State::getResY()/2.0f);
65  this->deathScreen->setVisibility(false);
66
67  this->localPlayer = State::getPlayer();
68
69  if( root != NULL)
70    this->loadParams(root);
71}
72
73/**
74 * decontsructor
75 */
76MultiplayerTeamDeathmatch::~MultiplayerTeamDeathmatch()
77{
78  if( this->deathScreen)
79    delete this->deathScreen;
80}
81
82
83
84void MultiplayerTeamDeathmatch::loadParams(const TiXmlElement* root)
85{
86  GameRules::loadParams(root) ;
87
88  LoadParam(root, "death-penalty-timeout", this, MultiplayerTeamDeathmatch, setDeathPenaltyTimeout)
89      .describe("sets the time in seconds a player has to wait for respawn");
90
91  LoadParam(root, "max-kills", this, MultiplayerTeamDeathmatch, setMaxKills)
92      .describe("sets the maximal kills for winning condition");
93
94  LoadParam(root, "death-screen-image", this, MultiplayerTeamDeathmatch, setDeathScreen)
95      .describe("sets the death screen image");
96 
97  LoadParam(root, "num-teams", this, MultiplayerTeamDeathmatch, setNumTeams)
98      .describe("sets number of teams");
99
100}
101
102
103
104void MultiplayerTeamDeathmatch::setDeathScreen(const std::string& imageName)
105{
106  if( this->deathScreen)
107    this->deathScreen->setTexture(imageName);
108}
109
110
111
112/**
113 * called when the player enters the game
114 * @param player the spawned player
115 */
116void MultiplayerTeamDeathmatch::onPlayerSpawn()
117{
118  this->bLocalPlayerDead = false;
119  this->deathScreen->setVisibility(false);
120}
121
122
123/**
124 * when the player is killed
125 * @param player the killed player
126 */
127void MultiplayerTeamDeathmatch::onPlayerDeath()
128{
129  this->bLocalPlayerDead = true;
130  this->deathScreen->setVisibility(true);
131}
132
133
134/**
135 * time tick
136 * @param dt time
137 */
138void MultiplayerTeamDeathmatch::tick(float dt)
139{
140  if ( !SharedNetworkData::getInstance()->isGameServer() )
141    return;
142 
143  gameStateTimer -= dt;
144  PRINTF(0)("TICK %f\n", gameStateTimer);
145 
146  if ( currentGameState != GAMESTATE_GAME && gameStateTimer < 0 )
147    nextGameState();
148 
149  this->currentGameState = NetworkGameManager::getInstance()->getGameState();
150 
151  if ( currentGameState == GAMESTATE_GAME )
152  {
153    handleTeamChanges();
154  }
155 
156  this->calculateTeamScore();
157 
158  this->checkGameRules();
159
160  // is the local player dead and inactive
161  if( unlikely(this->bLocalPlayerDead))
162  {
163    this->timeout += dt;
164    PRINTF(0)("TICK DEATH: %f of %f\n", this->timeout, this->deathTimeout);
165    // long enough dead?
166    if( this->timeout >= this->deathTimeout)
167    {
168      this->timeout = 0.0f;
169      // respawn
170      PRINTF(0)("RESPAWN\n");
171      (State::getPlayer())->getPlayable()->respawn();
172    }
173  }
174}
175
176
177/**
178 * draws the stuff
179 */
180void MultiplayerTeamDeathmatch::draw()
181{
182  if( unlikely( this->bLocalPlayerDead))
183  {
184
185  }
186}
187
188
189/**
190 * check the game rules for consistency
191 */
192void MultiplayerTeamDeathmatch::checkGameRules()
193{
194  if ( !SharedNetworkData::getInstance()->isGameServer() )
195    return;
196 
197  // check for max killing count
198  for ( int i = 0; i<numTeams; i++ )
199  {
200    if ( teamScore[i] >= maxKills )
201    {
202      //team i wins
203      //TODO
204    }
205  }
206}
207
208/**
209 * find group for new player
210 * @return group id
211 */
212int MultiplayerTeamDeathmatch::getTeamForNewUser( )
213{
214  return TEAM_NOTEAM;
215}
216
217ClassID MultiplayerTeamDeathmatch::getPlayableClassId( int team )
218{
219  return CL_SPECTATOR;
220}
221
222std::string MultiplayerTeamDeathmatch::getPlayableModelFileName( int team, ClassID classId )
223{
224  return "";
225}
226
227/**
228 * calculate team score
229 */
230void MultiplayerTeamDeathmatch::calculateTeamScore( )
231{
232  teamScore.clear();
233 
234  for ( int i = 0; i<numTeams; i++ )
235    teamScore[i] = 0;
236 
237   
238  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
239 
240  if ( !list )
241    return;
242 
243  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
244  {
245    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
246
247    if ( stats.getTeamId() >= 0 )
248    {
249      teamScore[stats.getTeamId()] += stats.getScore();
250    }
251  }
252}
253
254/**
255 * get team for player who choose to join random team
256 * @return smallest team
257 */
258int MultiplayerTeamDeathmatch::getRandomTeam( )
259{
260  std::map<int,int> playersInTeam;
261 
262  for ( int i = 0; i<numTeams; i++ )
263    playersInTeam[i] = 0;
264 
265  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
266 
267  if ( !list )
268    return 0;
269 
270  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
271  {
272    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
273
274    if ( stats.getTeamId() >= 0 )
275    {
276      playersInTeam[stats.getTeamId()]++;
277    }
278  }
279 
280 
281  int minPlayers = 0xFFFF;
282  int minTeam = -1;
283 
284  for ( int i = 0; i<numTeams; i++ )
285  {
286    if ( playersInTeam[i] < minPlayers )
287    {
288      minTeam = i;
289      minPlayers = playersInTeam[i];
290    }
291  }
292 
293  assert( minTeam != -1 );
294 
295  return minTeam;
296}
297
298void MultiplayerTeamDeathmatch::nextGameState( )
299{
300  if ( currentGameState == GAMESTATE_PRE_GAME )
301  {
302    NetworkGameManager::getInstance()->setGameState( GAMESTATE_GAME );
303   
304    return;
305  }
306 
307  if ( currentGameState == GAMESTATE_GAME )
308  {
309    NetworkGameManager::getInstance()->setGameState( GAMESTATE_POST_GAME );
310   
311    return;
312  }
313 
314  if ( currentGameState == GAMESTATE_POST_GAME )
315  {
316    //TODO end game
317   
318    return;
319  }
320}
321
322void MultiplayerTeamDeathmatch::handleTeamChanges( )
323{
324  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
325 
326  if ( !list )
327    return;
328 
329  //first server players with choices
330  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
331  {
332    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
333
334    if ( stats.getTeamId() != stats.getPreferedTeamId() )
335    {
336      if ( stats.getPreferedTeamId() == TEAM_SPECTATOR || ( stats.getPreferedTeamId() <= 0 && stats.getPreferedTeamId() < numTeams ) )
337      {
338        teamChange( stats.getUserId() );
339      }
340    }
341  }
342 
343  //now serve player who want join a random team
344  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
345  {
346    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
347
348    if ( stats.getTeamId() != stats.getPreferedTeamId() )
349    {
350      if ( stats.getPreferedTeamId() == TEAM_RANDOM )
351      {
352        stats.setPreferedTeamId( getTeamForNewUser() );
353        teamChange( stats.getUserId() );
354      }
355    }
356  }
357}
358
359void MultiplayerTeamDeathmatch::teamChange( int userId )
360{
361  assert( PlayerStats::getStats( userId ) );
362  PlayerStats & stats = *(PlayerStats::getStats( userId ));
363 
364  assert(false);
365}
366
367
368
369
370
371
Note: See TracBrowser for help on using the repository browser.