Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

trunk: merged the network branche back to trunk

File size: 7.8 KB
RevLine 
[7034]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
[8068]17#include <map>
18
[7034]19#include "multiplayer_team_deathmatch.h"
20
[7193]21#include "util/loading/load_param.h"
22#include "util/loading/factory.h"
[7034]23
[7810]24#include "render2D/image_plane.h"
[7039]25#include "state.h"
[7101]26#include "class_list.h"
[7034]27
[7044]28#include "player.h"
29#include "playable.h"
[7101]30#include "space_ships/space_ship.h"
[7039]31
[7116]32
[7101]33#include "shared_network_data.h"
[7116]34#include "terrain.h"
35#include "class_list.h"
36#include "space_ships/space_ship.h"
[7044]37
[8068]38#include "network_game_manager.h"
[7101]39
[8068]40
[7034]41using namespace std;
42
43
[7035]44CREATE_FACTORY(MultiplayerTeamDeathmatch, CL_MULTIPLAYER_TEAM_DEATHMATCH);
45
46
[7034]47/**
48 * constructor
49 */
[7035]50MultiplayerTeamDeathmatch::MultiplayerTeamDeathmatch(const TiXmlElement* root)
[8068]51  : NetworkGameRules(root)
[7035]52{
53  this->setClassID(CL_MULTIPLAYER_TEAM_DEATHMATCH, "MultiplayerTeamDeathmatch");
[7034]54
[7037]55  this->bLocalPlayerDead = false;
56  this->deathTimeout = 10.0f;     // 5 seconds
[7082]57  this->timeout = 0.0f;
[8068]58  this->numTeams = 2;
59  this->currentGameState = GAMESTATE_PRE_GAME;
60  this->gameStateTimer = 10.0f;
[7040]61
[7810]62  this->deathScreen = new ImagePlane();
[7044]63  this->deathScreen->setSize(State::getResX()/4.0, State::getResY()/4.0);
[7040]64  this->deathScreen->setAbsCoor2D(State::getResX()/2.0f, State::getResY()/2.0f);
[7044]65  this->deathScreen->setVisibility(false);
[7037]66
[7044]67  this->localPlayer = State::getPlayer();
68
[7035]69  if( root != NULL)
70    this->loadParams(root);
71}
72
[7034]73/**
74 * decontsructor
75 */
76MultiplayerTeamDeathmatch::~MultiplayerTeamDeathmatch()
[7044]77{
78  if( this->deathScreen)
79    delete this->deathScreen;
80}
[7034]81
82
83
84void MultiplayerTeamDeathmatch::loadParams(const TiXmlElement* root)
[7035]85{
[7040]86  GameRules::loadParams(root) ;
[7037]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");
[7039]93
94  LoadParam(root, "death-screen-image", this, MultiplayerTeamDeathmatch, setDeathScreen)
95      .describe("sets the death screen image");
[8068]96 
97  LoadParam(root, "num-teams", this, MultiplayerTeamDeathmatch, setNumTeams)
98      .describe("sets number of teams");
[7039]99
[7035]100}
101
102
[7039]103
[7221]104void MultiplayerTeamDeathmatch::setDeathScreen(const std::string& imageName)
[7039]105{
106  if( this->deathScreen)
107    this->deathScreen->setTexture(imageName);
108}
109
110
111
[7035]112/**
113 * called when the player enters the game
114 * @param player the spawned player
115 */
[7044]116void MultiplayerTeamDeathmatch::onPlayerSpawn()
[7039]117{
[7044]118  this->bLocalPlayerDead = false;
119  this->deathScreen->setVisibility(false);
[7039]120}
[7034]121
[7035]122
123/**
124 * when the player is killed
125 * @param player the killed player
126 */
[7044]127void MultiplayerTeamDeathmatch::onPlayerDeath()
[7039]128{
129  this->bLocalPlayerDead = true;
[7044]130  this->deathScreen->setVisibility(true);
[7039]131}
[7035]132
133
134/**
135 * time tick
136 * @param dt time
137 */
138void MultiplayerTeamDeathmatch::tick(float dt)
[7037]139{
[8068]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 
[7039]158  this->checkGameRules();
[7035]159
[7039]160  // is the local player dead and inactive
161  if( unlikely(this->bLocalPlayerDead))
162  {
163    this->timeout += dt;
[7088]164    PRINTF(0)("TICK DEATH: %f of %f\n", this->timeout, this->deathTimeout);
[7039]165    // long enough dead?
[7044]166    if( this->timeout >= this->deathTimeout)
[7039]167    {
168      this->timeout = 0.0f;
169      // respawn
[7079]170      PRINTF(0)("RESPAWN\n");
[7044]171      (State::getPlayer())->getPlayable()->respawn();
[7039]172    }
173  }
[7037]174}
[7035]175
[7037]176
[7035]177/**
178 * draws the stuff
179 */
180void MultiplayerTeamDeathmatch::draw()
[7039]181{
182  if( unlikely( this->bLocalPlayerDead))
183  {
[7035]184
[7039]185  }
186}
[7035]187
[7039]188
[7035]189/**
190 * check the game rules for consistency
191 */
192void MultiplayerTeamDeathmatch::checkGameRules()
[7039]193{
[8068]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}
[7101]207
[8068]208/**
209 * find group for new player
210 * @return group id
211 */
212int MultiplayerTeamDeathmatch::getTeamForNewUser( )
213{
214  return TEAM_NOTEAM;
215}
[7101]216
[8068]217ClassID MultiplayerTeamDeathmatch::getPlayableClassId( int team )
218{
219  return CL_SPECTATOR;
220}
[7101]221
[8068]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++ )
[7039]244  {
[8068]245    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
246
247    if ( stats.getTeamId() >= 0 )
248    {
249      teamScore[stats.getTeamId()] += stats.getScore();
250    }
[7039]251  }
[8068]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++ )
[7039]271  {
[8068]272    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
273
274    if ( stats.getTeamId() >= 0 )
275    {
276      playersInTeam[stats.getTeamId()]++;
277    }
[7039]278  }
[8068]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}
[7101]297
[8068]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}
[7118]321
[8068]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++ )
[7116]331  {
[8068]332    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
[7118]333
[8068]334    if ( stats.getTeamId() != stats.getPreferedTeamId() )
[7116]335    {
[8068]336      if ( stats.getPreferedTeamId() == TEAM_SPECTATOR || ( stats.getPreferedTeamId() <= 0 && stats.getPreferedTeamId() < numTeams ) )
[7116]337      {
[8068]338        teamChange( stats.getUserId() );
[7116]339      }
340    }
341  }
[8068]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);
[7101]347
[8068]348    if ( stats.getTeamId() != stats.getPreferedTeamId() )
[7101]349    {
[8068]350      if ( stats.getPreferedTeamId() == TEAM_RANDOM )
[7101]351      {
[8068]352        stats.setPreferedTeamId( getTeamForNewUser() );
353        teamChange( stats.getUserId() );
[7101]354      }
355    }
356  }
[8068]357}
[7101]358
[8068]359void MultiplayerTeamDeathmatch::teamChange( int userId )
360{
361  assert( PlayerStats::getStats( userId ) );
362  PlayerStats & stats = *(PlayerStats::getStats( userId ));
363 
364  assert(false);
[7039]365}
[7035]366
367
368
369
370
371
Note: See TracBrowser for help on using the repository browser.