Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/multi_player_map/src/util/multiplayer_team_deathmatch.cc @ 8856

Last change on this file since 8856 was 8856, checked in by rennerc, 18 years ago

fixed segfault

File size: 19.7 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
[8147]40#include "event_handler.h"
[8068]41
[8147]42#include "glgui.h"
43
44#include "story_entity.h"
45
[8708]46#include "shell_command.h"
[8147]47
[8802]48#include "spawning_point.h"
[8708]49
[8802]50
[7034]51using namespace std;
52
53
[7035]54CREATE_FACTORY(MultiplayerTeamDeathmatch, CL_MULTIPLAYER_TEAM_DEATHMATCH);
55
56
[7034]57/**
58 * constructor
59 */
[7035]60MultiplayerTeamDeathmatch::MultiplayerTeamDeathmatch(const TiXmlElement* root)
[8068]61  : NetworkGameRules(root)
[7035]62{
63  this->setClassID(CL_MULTIPLAYER_TEAM_DEATHMATCH, "MultiplayerTeamDeathmatch");
[7034]64
[7037]65  this->bLocalPlayerDead = false;
66  this->deathTimeout = 10.0f;     // 5 seconds
[7082]67  this->timeout = 0.0f;
[8068]68  this->numTeams = 2;
69  this->currentGameState = GAMESTATE_PRE_GAME;
[8856]70  this->gameStateTimer = 3.0f;
[8623]71  this->bShowTeamChange = false;
[8717]72
[8147]73  this->box = NULL;
[8802]74  this->table = NULL;
75  this->statsBox = NULL;
[7040]76
[7044]77  this->localPlayer = State::getPlayer();
78
[7035]79  if( root != NULL)
80    this->loadParams(root);
[8717]81
[8623]82  subscribeEvent( ES_GAME, SDLK_o );
[8851]83  subscribeEvent( ES_GAME, SDLK_TAB );
[8802]84  subscribeEvent( ES_GAME, SDLK_F1 );
85  subscribeEvent( ES_MENU, SDLK_F1 );
86  subscribeEvent( ES_MENU, KeyMapper::PEV_FIRE1 );
[8838]87
[8708]88  this->notifier = new OrxGui::GLGuiNotifier();
89  this->notifier->show();
90  this->notifier->setAbsCoor2D(5, 30);
91  this->notifier->setFadeAge( 6.0 );
92  this->notifier->setHideAge( 8.0 );
93  this->input = new OrxGui::GLGuiInputLine();
94  this->input->setAbsCoor2D(180, 5);
95  this->input->connect(SIGNAL(input, enterPushed), this, SLOT(MultiplayerTeamDeathmatch, onInputEnter));
[7035]96}
97
[7034]98/**
99 * decontsructor
100 */
101MultiplayerTeamDeathmatch::~MultiplayerTeamDeathmatch()
[7044]102{
[8623]103  unsubscribeEvent( ES_GAME, SDLK_o );
[8851]104  unsubscribeEvent( ES_GAME, SDLK_TAB );
[8802]105  unsubscribeEvent( ES_GAME, SDLK_F1 );
106  unsubscribeEvent( ES_MENU, SDLK_F1 );
107  unsubscribeEvent( ES_MENU, KeyMapper::PEV_FIRE1 );
[8838]108
[8708]109  if ( this->notifier )
110  {
111    delete this->notifier;
112    this->notifier = NULL;
113  }
[8717]114
[8708]115  if ( this->input )
116  {
117    delete this->input;
118    this->input = NULL;
119  }
[7044]120}
[7034]121
122
123
124void MultiplayerTeamDeathmatch::loadParams(const TiXmlElement* root)
[7035]125{
[7040]126  GameRules::loadParams(root) ;
[7037]127
128  LoadParam(root, "death-penalty-timeout", this, MultiplayerTeamDeathmatch, setDeathPenaltyTimeout)
129      .describe("sets the time in seconds a player has to wait for respawn");
130
131  LoadParam(root, "max-kills", this, MultiplayerTeamDeathmatch, setMaxKills)
132      .describe("sets the maximal kills for winning condition");
[7039]133
[8068]134  LoadParam(root, "num-teams", this, MultiplayerTeamDeathmatch, setNumTeams)
135      .describe("sets number of teams");
[7039]136
[7035]137}
138
139
140/**
141 * time tick
142 * @param dt time
143 */
144void MultiplayerTeamDeathmatch::tick(float dt)
[7037]145{
[8802]146  tickStatsTable();
[8147]147  //on client side hostId is -1 until hanshake finished
148  if ( SharedNetworkData::getInstance()->getHostID() < 0 )
149    return;
[8717]150
[8623]151  if ( currentGameState == GAMESTATE_PRE_GAME || currentGameState == GAMESTATE_GAME )
[8147]152  {
153    if ( PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )
154         && box == NULL
[8717]155         &&  (PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPreferedTeamId() == TEAM_NOTEAM
[8623]156         || bShowTeamChange )
[8717]157
[8147]158       )
159    {
160      EventHandler::getInstance()->pushState( ES_MENU );
[8717]161
[8147]162      OrxGui::GLGuiHandler::getInstance()->activateCursor();
[8717]163
[8147]164      box = new OrxGui::GLGuiBox();
165      box->setAbsCoor2D( 300, 100 );
[8717]166
[8147]167      OrxGui::GLGuiPushButton * buttonSpectator = new OrxGui::GLGuiPushButton("Spectator");
168      box->pack( buttonSpectator );
169      buttonSpectator->connect(SIGNAL(buttonSpectator, released), this, SLOT(MultiplayerTeamDeathmatch, onButtonSpectator));
[8717]170
[8147]171      OrxGui::GLGuiPushButton * buttonRandom = new OrxGui::GLGuiPushButton("Random");
172      box->pack( buttonRandom );
173      buttonRandom->connect(SIGNAL(buttonRandom, released), this, SLOT(MultiplayerTeamDeathmatch, onButtonRandom));
[8717]174
[8147]175      OrxGui::GLGuiPushButton * buttonTeam0 = new OrxGui::GLGuiPushButton("Blue Team");
176      box->pack( buttonTeam0 );
177      buttonTeam0->connect(SIGNAL(buttonTeam0, released), this, SLOT(MultiplayerTeamDeathmatch, onButtonTeam0));
[8717]178
[8147]179      OrxGui::GLGuiPushButton * buttonTeam1 = new OrxGui::GLGuiPushButton("Red Team");
180      box->pack( buttonTeam1 );
181      buttonTeam1->connect(SIGNAL(buttonTeam1, released), this, SLOT(MultiplayerTeamDeathmatch, onButtonTeam1));
[8717]182
[8623]183      if ( bShowTeamChange )
184      {
185        OrxGui::GLGuiPushButton * buttonCancel = new OrxGui::GLGuiPushButton("Cancel");
186        box->pack( buttonCancel );
187        buttonCancel->connect(SIGNAL(buttonCancel, released), this, SLOT(MultiplayerTeamDeathmatch, onButtonCancel));
188      }
[8717]189
[8147]190      OrxGui::GLGuiPushButton * buttonExit = new OrxGui::GLGuiPushButton("Exit");
191      box->pack( buttonExit );
192      buttonExit->connect(SIGNAL(buttonExit, released), this, SLOT(MultiplayerTeamDeathmatch, onButtonExit));
[8717]193
[8147]194      box->showAll();
195    }
196  }
197
198  if ( box != NULL
199       && PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )
[8717]200       && PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPreferedTeamId() != TEAM_NOTEAM
[8623]201       && !bShowTeamChange
[8147]202     )
203  {
204    delete box;
205    box = NULL;
[8717]206
[8147]207    OrxGui::GLGuiHandler::getInstance()->deactivateCursor( true );
[8717]208
[8147]209    EventHandler::getInstance()->popState();
210  }
[8717]211
[8147]212  if ( box != NULL )
213  {
214    OrxGui::GLGuiHandler::getInstance()->tick( dt );
215  }
[8717]216
[8147]217  assignPlayable();
[8717]218
[8068]219  if ( !SharedNetworkData::getInstance()->isGameServer() )
220    return;
[8838]221
[8802]222  //handle kills
[8856]223  while ( this->killList.begin() != this->killList.end() )
[8802]224  {
[8856]225    if ( this->killList.begin()->getKiller() != NULL && this->killList.begin()->getVictim() != NULL )
226      onKill( this->killList.begin()->getKiller()->getOwner(), this->killList.begin()->getVictim()->getOwner() );
227    this->killList.erase( this->killList.begin() );
228  }
229 
[8838]230
231
[8068]232  gameStateTimer -= dt;
[8147]233  //PRINTF(0)("TICK %f\n", gameStateTimer);
[8717]234
[8068]235  if ( currentGameState != GAMESTATE_GAME && gameStateTimer < 0 )
236    nextGameState();
[8717]237
[8068]238  this->currentGameState = NetworkGameManager::getInstance()->getGameState();
[8717]239
[8068]240  if ( currentGameState == GAMESTATE_GAME )
241  {
242    handleTeamChanges();
243  }
[8717]244
[8068]245  this->calculateTeamScore();
[8717]246
[7039]247  this->checkGameRules();
[7035]248
[7039]249  // is the local player dead and inactive
250  if( unlikely(this->bLocalPlayerDead))
251  {
252    this->timeout += dt;
[7088]253    PRINTF(0)("TICK DEATH: %f of %f\n", this->timeout, this->deathTimeout);
[7039]254    // long enough dead?
[7044]255    if( this->timeout >= this->deathTimeout)
[7039]256    {
257      this->timeout = 0.0f;
258      // respawn
[7079]259      PRINTF(0)("RESPAWN\n");
[7044]260      (State::getPlayer())->getPlayable()->respawn();
[7039]261    }
262  }
[7037]263}
[7035]264
[7037]265
[7035]266/**
267 * draws the stuff
268 */
269void MultiplayerTeamDeathmatch::draw()
[7039]270{
271  if( unlikely( this->bLocalPlayerDead))
272  {
[7035]273
[7039]274  }
275}
[7035]276
[7039]277
[7035]278/**
279 * check the game rules for consistency
280 */
281void MultiplayerTeamDeathmatch::checkGameRules()
[7039]282{
[8068]283  if ( !SharedNetworkData::getInstance()->isGameServer() )
284    return;
[8717]285
[8068]286  // check for max killing count
287  for ( int i = 0; i<numTeams; i++ )
288  {
289    if ( teamScore[i] >= maxKills )
290    {
[8802]291      nextGameState();
[8068]292    }
293  }
294}
[7101]295
[8068]296/**
297 * find group for new player
298 * @return group id
299 */
[8147]300int MultiplayerTeamDeathmatch::getTeamForNewUser()
[8068]301{
302  return TEAM_NOTEAM;
303}
[7101]304
[8147]305ClassID MultiplayerTeamDeathmatch::getPlayableClassId( int userId, int team )
[8068]306{
[8147]307  if ( team == TEAM_NOTEAM || team == TEAM_SPECTATOR )
308    return CL_SPECTATOR;
[8717]309
[8147]310  if ( team == 0 || team == 1 )
311    return CL_SPACE_SHIP;
[8717]312
[8147]313  assert( false );
[8068]314}
[7101]315
[8147]316std::string MultiplayerTeamDeathmatch::getPlayableModelFileName( int userId, int team, ClassID classId )
[8068]317{
[8147]318  if ( team == 0 )
319    return "models/ships/reap_#.obj";
320  else if ( team == 1 )
321    return "models/ships/fighter.obj";
322  else
323    return "";
[8068]324}
325
326/**
327 * calculate team score
328 */
329void MultiplayerTeamDeathmatch::calculateTeamScore( )
330{
331  teamScore.clear();
[8717]332
[8068]333  for ( int i = 0; i<numTeams; i++ )
334    teamScore[i] = 0;
[8717]335
336
[8068]337  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
[8717]338
[8068]339  if ( !list )
340    return;
[8717]341
[8068]342  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
[7039]343  {
[8068]344    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
345
346    if ( stats.getTeamId() >= 0 )
347    {
348      teamScore[stats.getTeamId()] += stats.getScore();
349    }
[7039]350  }
[8068]351}
352
353/**
354 * get team for player who choose to join random team
355 * @return smallest team
356 */
357int MultiplayerTeamDeathmatch::getRandomTeam( )
358{
359  std::map<int,int> playersInTeam;
[8717]360
[8068]361  for ( int i = 0; i<numTeams; i++ )
362    playersInTeam[i] = 0;
[8717]363
[8068]364  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
[8717]365
[8068]366  if ( !list )
367    return 0;
[8717]368
[8068]369  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
[7039]370  {
[8068]371    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
372
373    if ( stats.getTeamId() >= 0 )
374    {
375      playersInTeam[stats.getTeamId()]++;
376    }
[7039]377  }
[8717]378
379
[8068]380  int minPlayers = 0xFFFF;
381  int minTeam = -1;
[8717]382
[8068]383  for ( int i = 0; i<numTeams; i++ )
384  {
385    if ( playersInTeam[i] < minPlayers )
386    {
387      minTeam = i;
388      minPlayers = playersInTeam[i];
389    }
390  }
[8717]391
[8068]392  assert( minTeam != -1 );
[8717]393
[8068]394  return minTeam;
395}
[7101]396
[8068]397void MultiplayerTeamDeathmatch::nextGameState( )
398{
399  if ( currentGameState == GAMESTATE_PRE_GAME )
400  {
401    NetworkGameManager::getInstance()->setGameState( GAMESTATE_GAME );
[8717]402
[8068]403    return;
404  }
[8717]405
[8068]406  if ( currentGameState == GAMESTATE_GAME )
407  {
408    NetworkGameManager::getInstance()->setGameState( GAMESTATE_POST_GAME );
[8717]409
[8068]410    return;
411  }
[8717]412
[8068]413  if ( currentGameState == GAMESTATE_POST_GAME )
414  {
[8802]415    State::getCurrentStoryEntity()->stop();
416    this->bShowTeamChange = false;
[8717]417
[8068]418    return;
419  }
420}
[7118]421
[8068]422void MultiplayerTeamDeathmatch::handleTeamChanges( )
423{
424  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
[8717]425
[8068]426  if ( !list )
427    return;
[8717]428
[8068]429  //first server players with choices
430  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
[7116]431  {
[8068]432    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
[7118]433
[8068]434    if ( stats.getTeamId() != stats.getPreferedTeamId() )
[7116]435    {
[8147]436      if ( stats.getPreferedTeamId() == TEAM_SPECTATOR || ( stats.getPreferedTeamId() >= 0 && stats.getPreferedTeamId() < numTeams ) )
[7116]437      {
[8068]438        teamChange( stats.getUserId() );
[7116]439      }
440    }
441  }
[8717]442
[8068]443  //now serve player who want join a random team
444  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
445  {
446    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
[7101]447
[8068]448    if ( stats.getTeamId() != stats.getPreferedTeamId() )
[7101]449    {
[8068]450      if ( stats.getPreferedTeamId() == TEAM_RANDOM )
[7101]451      {
[8147]452        stats.setPreferedTeamId( getRandomTeam() );
[8068]453        teamChange( stats.getUserId() );
[7101]454      }
455    }
456  }
[8068]457}
[7101]458
[8068]459void MultiplayerTeamDeathmatch::teamChange( int userId )
460{
461  assert( PlayerStats::getStats( userId ) );
462  PlayerStats & stats = *(PlayerStats::getStats( userId ));
[8717]463
[8147]464  stats.setTeamId( stats.getPreferedTeamId() );
[8717]465
[8147]466  Playable * oldPlayable = stats.getPlayable();
[8717]467
468
[8147]469  ClassID playableClassId = getPlayableClassId( userId, stats.getPreferedTeamId() );
470  std::string playableModel = getPlayableModelFileName( userId, stats.getPreferedTeamId(), playableClassId );
[8717]471
[8147]472  BaseObject * bo = Factory::fabricate( playableClassId );
[8717]473
[8147]474  assert( bo != NULL );
475  assert( bo->isA( CL_PLAYABLE ) );
[8717]476
[8147]477  Playable & playable = *(dynamic_cast<Playable*>(bo));
[8717]478
[8147]479  playable.loadModel( playableModel );
480  playable.setOwner( userId );
481  playable.setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
482  playable.setSynchronized( true );
[8838]483
[8147]484  stats.setTeamId( stats.getPreferedTeamId() );
485  stats.setPlayableClassId( playableClassId );
486  stats.setPlayableUniqueId( playable.getUniqueID() );
487  stats.setModelFileName( playableModel );
[8838]488
[8827]489  this->respawnPlayable( &playable, stats.getPreferedTeamId(), 0.0f );
[8717]490
[8147]491  if ( oldPlayable )
492  {
493    //if ( userId == SharedNetworkData::getInstance()->getHostID() )
494    //  State::getPlayer()->setPlayable( NULL );
495    delete oldPlayable;
496  }
[7039]497}
[7035]498
[8147]499void MultiplayerTeamDeathmatch::onButtonExit( )
500{
501  State::getCurrentStoryEntity()->stop();
[8623]502  this->bShowTeamChange = false;
[8147]503}
[7035]504
[8147]505void MultiplayerTeamDeathmatch::onButtonRandom( )
506{
507  NetworkGameManager::getInstance()->prefereTeam( TEAM_RANDOM );
[8623]508  this->bShowTeamChange = false;
[8147]509}
[7035]510
[8147]511void MultiplayerTeamDeathmatch::onButtonTeam0( )
512{
513  NetworkGameManager::getInstance()->prefereTeam( 0 );
[8623]514  this->bShowTeamChange = false;
[8147]515}
[7035]516
[8147]517void MultiplayerTeamDeathmatch::onButtonTeam1( )
518{
519  NetworkGameManager::getInstance()->prefereTeam( 1 );
[8623]520  this->bShowTeamChange = false;
[8147]521}
[7035]522
[8147]523void MultiplayerTeamDeathmatch::onButtonSpectator( )
524{
525  NetworkGameManager::getInstance()->prefereTeam( TEAM_SPECTATOR );
[8623]526  this->bShowTeamChange = false;
[8147]527}
[7035]528
[8147]529void MultiplayerTeamDeathmatch::assignPlayable( )
530{
531  if ( PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() ) )
532    PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPlayable();
533}
534
[8623]535  /**
536   * function that processes events from the handler
537   * @param event: the event
538   * @todo replace SDLK_o with something from KeyMapper
539   */
540void MultiplayerTeamDeathmatch::process( const Event & event )
541{
542  if ( event.type == SDLK_o )
543  {
544    if ( event.bPressed )
545      this->bShowTeamChange = true;
[8802]546  } else if ( event.type == SDLK_F1 )
547  {
548    if ( !this->statsBox && event.bPressed )
549    {
550      PRINTF(0)("show stats\n");
551      this->showStats();
552    }
553    if ( this->statsBox && !this->bLocalPlayerDead && event.bPressed && this->table->rowCount() != 0 && this->table->columnCount() != 0 )
554    {
555      PRINTF(0)("hide stats\n");
556      this->hideStats();
557    }
[8623]558  }
[8851]559  else if ( event.type == SDLK_TAB )
[8708]560  {
[8851]561    if ( currentGameState == GAMESTATE_GAME && !event.bPressed && !EventHandler::getInstance()->isPressed( SDLK_RALT ) && !EventHandler::getInstance()->isPressed( SDLK_LALT ) )
[8708]562    {
563      EventHandler::getInstance()->pushState( ES_MENU );
564      OrxGui::GLGuiHandler::getInstance()->activateCursor();
565      OrxGui::GLGuiHandler::getInstance()->deactivateCursor();
566      input->show();
[8717]567      input->giveMouseFocus();
[8708]568      input->setText("say ");
569    }
570  }
[8802]571  else if ( this->bLocalPlayerDead && statsBox && event.type == KeyMapper::PEV_FIRE1 )
572  {
573    this->hideStats();
574  }
[8623]575}
[8147]576
[8623]577void MultiplayerTeamDeathmatch::onButtonCancel( )
578{
579  this->bShowTeamChange = false;
580}
[8147]581
582
583
[8623]584/**
585 * this method is called by NetworkGameManger when he recieved a chat message
586 * @param userId senders user id
587 * @param message message string
588 * @param messageType some int
589 */
590void MultiplayerTeamDeathmatch::handleChatMessage( int userId, const std::string & message, int messageType )
591{
592  std::string name = "unknown";
[8717]593
[8623]594  if ( PlayerStats::getStats( userId ) )
595  {
596    name = PlayerStats::getStats( userId )->getNickName();
597  }
[8717]598
[8708]599  PRINTF(0)("CHATMESSAGE %s (%d): %s\n", name.c_str(), userId, message.c_str() );
600  notifier->pushNotifyMessage(name + ": " + message);
[8623]601}
[8147]602
[8708]603void MultiplayerTeamDeathmatch::onInputEnter( const std::string & text )
604{
605  EventHandler::getInstance()->popState();
[8717]606  input->breakMouseFocus();
[8708]607  input->hide();
608  input->setText("");
[8623]609
[8708]610  std::string command = text;
[8717]611
[8708]612  //HACK insert " in say commands so user doesn't have to type them
613  if ( command.length() >= 4 && command[0] == 's' && command[1] == 'a' && command[2] == 'y' && command[3] == ' ' )
614  {
615    command.insert( 4, "\"" );
616    command = command + "\"";
617  }
[8623]618
[8708]619  OrxShell::ShellCommand::execute( command );
620}
[8623]621
[8802]622/**
623 * show table with frags
624 */
625void MultiplayerTeamDeathmatch::showStats( )
626{
627  EventHandler::getInstance()->pushState( ES_MENU );
628  statsBox = new OrxGui::GLGuiBox();
629  statsBox->setAbsCoor2D( 300, 100 );
[8838]630
[8802]631  this->table = new OrxGui::GLGuiTable(0,0);
[8708]632
[8802]633  statsBox->pack( this->table );
[8708]634
[8802]635  statsBox->showAll();
636}
[8708]637
[8802]638/**
639 * hide table with frags
640 */
641void MultiplayerTeamDeathmatch::hideStats( )
642{
643    if ( statsBox )
644    {
645      delete statsBox;
646      statsBox = NULL;
647    }
[8838]648
[8802]649    EventHandler::getInstance()->popState();
650}
651
652/**
653 * fill stats table with values
654 */
655void MultiplayerTeamDeathmatch::tickStatsTable( )
656{
657  if ( !this->statsBox )
658    return;
659
660  std::vector<std::string> headers;
661  headers.push_back("Red Team");
662  headers.push_back("");
663  headers.push_back("");
664  headers.push_back("Blue Team");
665  headers.push_back("");
666  this->table->setHeader(headers);
[8838]667
[8802]668  std::map<int,std::string> fragsTeam0;
669  std::map<int,std::string> fragsTeam1;
[8838]670
[8802]671  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
[8838]672
[8802]673  if ( !list )
674    return;
[8838]675
[8802]676  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
677  {
678    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
[8838]679
[8802]680    if ( stats.getTeamId() == 0 || stats.getTeamId() == 1 )
681    {
682      if ( stats.getTeamId() == 0 )
683        fragsTeam0[stats.getScore()] = stats.getNickName();
684      else
685        fragsTeam1[stats.getScore()] = stats.getNickName();
686    }
687  }
[8838]688
[8802]689  char st[10];
690  int i = 0;
[8838]691
692
[8802]693  i = 2;
694  for ( std::map<int,std::string>::const_iterator it = fragsTeam0.begin(); it != fragsTeam0.end(); it++ )
695  {
696    this->table->setEntry( 0, i, it->second );
697    snprintf( st, 10, "%d", it->first );
698    this->table->setEntry( 1, i, st );
699    this->table->setEntry( 2, i, "" );
700    i++;
701  }
[8838]702
[8802]703  i = 2;
704  for ( std::map<int,std::string>::const_iterator it = fragsTeam1.begin(); it != fragsTeam1.end(); it++ )
705  {
706    this->table->setEntry( 3, i, it->second );
707    snprintf( st, 10, "%d", it->first );
708    this->table->setEntry( 4, i, st );
709    i++;
710  }
711}
712
713/**
714 * this function is called when a player kills another one or himself
[8838]715 * @param killedUserId
716 * @param userId
[8802]717 */
718void MultiplayerTeamDeathmatch::onKill( int killedUserId, int userId )
719{
720  assert( PlayerStats::getStats( killedUserId ) );
721  assert( PlayerStats::getStats( userId ) );
[8838]722
[8802]723  PlayerStats & killedStats = *PlayerStats::getStats( killedUserId );
724  PlayerStats & stats = *PlayerStats::getStats( userId );
[8838]725
[8802]726  if ( killedUserId != userId )
727    stats.setScore( stats.getScore() + 1 );
728  else
729    stats.setScore( stats.getScore() - 1 );
[8838]730
[8802]731  if ( killedUserId == SharedNetworkData::getInstance()->getHostID() )
732  {
733    this->bLocalPlayerDead = true;
734    this->showStats();
735  }
[8838]736
[8827]737  this->respawnPlayable( killedStats.getPlayable(), killedStats.getTeamId(), 3.0f );
[8802]738}
739
740/**
741 * this function is called on player respawn
[8838]742 * @param userId
[8802]743 */
744void MultiplayerTeamDeathmatch::onRespawn( int userId )
745{
746  if ( userId == SharedNetworkData::getInstance()->getHostID() )
747  {
748    this->bLocalPlayerDead = false;
749    this->hideStats();
750  }
751}
752
753/**
754 * this function is called on player respawn
[8838]755 * @param we
[8802]756 */
757void MultiplayerTeamDeathmatch::registerSpawn( WorldEntity * we )
758{
759  onRespawn( we->getOwner() );
760}
761
[8838]762
[8827]763void MultiplayerTeamDeathmatch::respawnPlayable( Playable * playable, int teamId, float delay )
764{
765  const std::list<BaseObject*> * list = ClassList::getList( CL_SPAWNING_POINT );
[8838]766
[8827]767  assert( list );
[8838]768
[8827]769  std::vector<SpawningPoint*> spList;
[8838]770
[8827]771  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
772  {
773    SpawningPoint * sp = dynamic_cast<SpawningPoint*>(*it);
[8838]774
[8827]775    if ( sp->getTeamId() == teamId )
776      spList.push_back( sp );
777  }
[8838]778
[8827]779  if ( spList.size() == 0 )
780  {
781    for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
782    {
783      SpawningPoint * sp = dynamic_cast<SpawningPoint*>(*it);
[8838]784
[8827]785      if ( sp->getTeamId() < 0 )
786        spList.push_back( sp );
787    }
788  }
[8838]789
[8827]790  assert( spList.size() != 0 );
[8838]791
[8827]792  int n = (int)((float)spList.size() * (float)rand()/(float)RAND_MAX);
[8838]793
[8827]794  spList[n]->pushEntity( playable, delay );
795}
796
Note: See TracBrowser for help on using the repository browser.