Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9023 was 9008, checked in by bensch, 18 years ago

orxonox/trunk: merged the network bak to the trunk
merged with command:
svn merge -r8804:HEAD https://svn.orxonox.net/orxonox/branches/multi_player_map .

conflicts all resolved in favour of the branche

File size: 20.0 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;
[9008]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 );
[8708]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 );
[9008]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 );
[8708]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 );
[9008]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;
[9008]221
[8802]222  //handle kills
[9008]223  while ( this->killList.begin() != this->killList.end() )
[8802]224  {
[9008]225    onKill( this->killList.begin()->getVictim(), this->killList.begin()->getKiller() );
226    this->killList.erase( this->killList.begin() );
[8802]227  }
228 
[9008]229
230
[8068]231  gameStateTimer -= dt;
[8147]232  //PRINTF(0)("TICK %f\n", gameStateTimer);
[8717]233
[8068]234  if ( currentGameState != GAMESTATE_GAME && gameStateTimer < 0 )
235    nextGameState();
[8717]236
[8068]237  this->currentGameState = NetworkGameManager::getInstance()->getGameState();
[8717]238
[8068]239  if ( currentGameState == GAMESTATE_GAME )
240  {
241    handleTeamChanges();
242  }
[8717]243
[8068]244  this->calculateTeamScore();
[8717]245
[7039]246  this->checkGameRules();
[7035]247
[7039]248  // is the local player dead and inactive
249  if( unlikely(this->bLocalPlayerDead))
250  {
251    this->timeout += dt;
[7088]252    PRINTF(0)("TICK DEATH: %f of %f\n", this->timeout, this->deathTimeout);
[7039]253    // long enough dead?
[7044]254    if( this->timeout >= this->deathTimeout)
[7039]255    {
256      this->timeout = 0.0f;
257      // respawn
[7079]258      PRINTF(0)("RESPAWN\n");
[7044]259      (State::getPlayer())->getPlayable()->respawn();
[7039]260    }
261  }
[7037]262}
[7035]263
[7037]264
[7035]265/**
266 * draws the stuff
267 */
268void MultiplayerTeamDeathmatch::draw()
[7039]269{
270  if( unlikely( this->bLocalPlayerDead))
271  {
[7035]272
[7039]273  }
274}
[7035]275
[7039]276
[7035]277/**
278 * check the game rules for consistency
279 */
280void MultiplayerTeamDeathmatch::checkGameRules()
[7039]281{
[8068]282  if ( !SharedNetworkData::getInstance()->isGameServer() )
283    return;
[8717]284
[8068]285  // check for max killing count
286  for ( int i = 0; i<numTeams; i++ )
287  {
288    if ( teamScore[i] >= maxKills )
289    {
[8802]290      nextGameState();
[8068]291    }
292  }
293}
[7101]294
[8068]295/**
296 * find group for new player
297 * @return group id
298 */
[8147]299int MultiplayerTeamDeathmatch::getTeamForNewUser()
[8068]300{
301  return TEAM_NOTEAM;
302}
[7101]303
[8147]304ClassID MultiplayerTeamDeathmatch::getPlayableClassId( int userId, int team )
[8068]305{
[8147]306  if ( team == TEAM_NOTEAM || team == TEAM_SPECTATOR )
307    return CL_SPECTATOR;
[8717]308
[8147]309  if ( team == 0 || team == 1 )
310    return CL_SPACE_SHIP;
[8717]311
[8147]312  assert( false );
[8068]313}
[7101]314
[8147]315std::string MultiplayerTeamDeathmatch::getPlayableModelFileName( int userId, int team, ClassID classId )
[8068]316{
[8147]317  if ( team == 0 )
318    return "models/ships/reap_#.obj";
319  else if ( team == 1 )
320    return "models/ships/fighter.obj";
321  else
322    return "";
[8068]323}
324
325/**
326 * calculate team score
327 */
328void MultiplayerTeamDeathmatch::calculateTeamScore( )
329{
330  teamScore.clear();
[8717]331
[8068]332  for ( int i = 0; i<numTeams; i++ )
333    teamScore[i] = 0;
[8717]334
335
[8068]336  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
[8717]337
[8068]338  if ( !list )
339    return;
[8717]340
[8068]341  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
[7039]342  {
[8068]343    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
344
345    if ( stats.getTeamId() >= 0 )
346    {
347      teamScore[stats.getTeamId()] += stats.getScore();
348    }
[7039]349  }
[8068]350}
351
352/**
353 * get team for player who choose to join random team
354 * @return smallest team
355 */
356int MultiplayerTeamDeathmatch::getRandomTeam( )
357{
358  std::map<int,int> playersInTeam;
[8717]359
[8068]360  for ( int i = 0; i<numTeams; i++ )
361    playersInTeam[i] = 0;
[8717]362
[8068]363  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
[8717]364
[8068]365  if ( !list )
366    return 0;
[8717]367
[8068]368  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
[7039]369  {
[8068]370    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
371
372    if ( stats.getTeamId() >= 0 )
373    {
374      playersInTeam[stats.getTeamId()]++;
375    }
[7039]376  }
[8717]377
378
[8068]379  int minPlayers = 0xFFFF;
380  int minTeam = -1;
[8717]381
[8068]382  for ( int i = 0; i<numTeams; i++ )
383  {
384    if ( playersInTeam[i] < minPlayers )
385    {
386      minTeam = i;
387      minPlayers = playersInTeam[i];
388    }
389  }
[8717]390
[8068]391  assert( minTeam != -1 );
[8717]392
[8068]393  return minTeam;
394}
[7101]395
[8068]396void MultiplayerTeamDeathmatch::nextGameState( )
397{
398  if ( currentGameState == GAMESTATE_PRE_GAME )
399  {
400    NetworkGameManager::getInstance()->setGameState( GAMESTATE_GAME );
[8717]401
[8068]402    return;
403  }
[8717]404
[8068]405  if ( currentGameState == GAMESTATE_GAME )
406  {
407    NetworkGameManager::getInstance()->setGameState( GAMESTATE_POST_GAME );
[8717]408
[8068]409    return;
410  }
[8717]411
[8068]412  if ( currentGameState == GAMESTATE_POST_GAME )
413  {
[8802]414    State::getCurrentStoryEntity()->stop();
415    this->bShowTeamChange = false;
[8717]416
[8068]417    return;
418  }
419}
[7118]420
[8068]421void MultiplayerTeamDeathmatch::handleTeamChanges( )
422{
423  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
[8717]424
[8068]425  if ( !list )
426    return;
[8717]427
[8068]428  //first server players with choices
429  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
[7116]430  {
[8068]431    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
[7118]432
[8068]433    if ( stats.getTeamId() != stats.getPreferedTeamId() )
[7116]434    {
[8147]435      if ( stats.getPreferedTeamId() == TEAM_SPECTATOR || ( stats.getPreferedTeamId() >= 0 && stats.getPreferedTeamId() < numTeams ) )
[7116]436      {
[8068]437        teamChange( stats.getUserId() );
[7116]438      }
439    }
440  }
[8717]441
[8068]442  //now serve player who want join a random team
443  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
444  {
445    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
[7101]446
[8068]447    if ( stats.getTeamId() != stats.getPreferedTeamId() )
[7101]448    {
[8068]449      if ( stats.getPreferedTeamId() == TEAM_RANDOM )
[7101]450      {
[8147]451        stats.setPreferedTeamId( getRandomTeam() );
[8068]452        teamChange( stats.getUserId() );
[7101]453      }
454    }
455  }
[8068]456}
[7101]457
[8068]458void MultiplayerTeamDeathmatch::teamChange( int userId )
459{
460  assert( PlayerStats::getStats( userId ) );
461  PlayerStats & stats = *(PlayerStats::getStats( userId ));
[8717]462
[8147]463  stats.setTeamId( stats.getPreferedTeamId() );
[8717]464
[8147]465  Playable * oldPlayable = stats.getPlayable();
[8717]466
467
[8147]468  ClassID playableClassId = getPlayableClassId( userId, stats.getPreferedTeamId() );
469  std::string playableModel = getPlayableModelFileName( userId, stats.getPreferedTeamId(), playableClassId );
[8717]470
[8147]471  BaseObject * bo = Factory::fabricate( playableClassId );
[8717]472
[8147]473  assert( bo != NULL );
474  assert( bo->isA( CL_PLAYABLE ) );
[8717]475
[8147]476  Playable & playable = *(dynamic_cast<Playable*>(bo));
[8717]477
[8147]478  playable.loadModel( playableModel );
479  playable.setOwner( userId );
480  playable.setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
481  playable.setSynchronized( true );
[8717]482
[8147]483  stats.setTeamId( stats.getPreferedTeamId() );
484  stats.setPlayableClassId( playableClassId );
485  stats.setPlayableUniqueId( playable.getUniqueID() );
486  stats.setModelFileName( playableModel );
[8717]487
[9008]488  this->respawnPlayable( &playable, stats.getPreferedTeamId(), 0.0f );
489
[8147]490  if ( oldPlayable )
491  {
492    //if ( userId == SharedNetworkData::getInstance()->getHostID() )
493    //  State::getPlayer()->setPlayable( NULL );
494    delete oldPlayable;
495  }
[7039]496}
[7035]497
[8147]498void MultiplayerTeamDeathmatch::onButtonExit( )
499{
500  State::getCurrentStoryEntity()->stop();
[8623]501  this->bShowTeamChange = false;
[8147]502}
[7035]503
[8147]504void MultiplayerTeamDeathmatch::onButtonRandom( )
505{
506  NetworkGameManager::getInstance()->prefereTeam( TEAM_RANDOM );
[8623]507  this->bShowTeamChange = false;
[8147]508}
[7035]509
[8147]510void MultiplayerTeamDeathmatch::onButtonTeam0( )
511{
512  NetworkGameManager::getInstance()->prefereTeam( 0 );
[8623]513  this->bShowTeamChange = false;
[8147]514}
[7035]515
[8147]516void MultiplayerTeamDeathmatch::onButtonTeam1( )
517{
518  NetworkGameManager::getInstance()->prefereTeam( 1 );
[8623]519  this->bShowTeamChange = false;
[8147]520}
[7035]521
[8147]522void MultiplayerTeamDeathmatch::onButtonSpectator( )
523{
524  NetworkGameManager::getInstance()->prefereTeam( TEAM_SPECTATOR );
[8623]525  this->bShowTeamChange = false;
[8147]526}
[7035]527
[8147]528void MultiplayerTeamDeathmatch::assignPlayable( )
529{
530  if ( PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() ) )
531    PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPlayable();
532}
533
[8623]534  /**
535   * function that processes events from the handler
536   * @param event: the event
537   * @todo replace SDLK_o with something from KeyMapper
538   */
539void MultiplayerTeamDeathmatch::process( const Event & event )
540{
541  if ( event.type == SDLK_o )
542  {
543    if ( event.bPressed )
544      this->bShowTeamChange = true;
[8802]545  } else if ( event.type == SDLK_F1 )
546  {
547    if ( !this->statsBox && event.bPressed )
548    {
549      PRINTF(0)("show stats\n");
550      this->showStats();
551    }
552    if ( this->statsBox && !this->bLocalPlayerDead && event.bPressed && this->table->rowCount() != 0 && this->table->columnCount() != 0 )
553    {
554      PRINTF(0)("hide stats\n");
555      this->hideStats();
556    }
[8623]557  }
[8708]558  else if ( event.type == SDLK_TAB )
559  {
[9008]560    if ( currentGameState == GAMESTATE_GAME && event.bPressed && !EventHandler::getInstance()->isPressed( SDLK_RALT ) && !EventHandler::getInstance()->isPressed( SDLK_LALT ) )
[8708]561    {
562      EventHandler::getInstance()->pushState( ES_MENU );
563      OrxGui::GLGuiHandler::getInstance()->activateCursor();
564      OrxGui::GLGuiHandler::getInstance()->deactivateCursor();
565      input->show();
[8717]566      input->giveMouseFocus();
[8708]567      input->setText("say ");
568    }
569  }
[8802]570  else if ( this->bLocalPlayerDead && statsBox && event.type == KeyMapper::PEV_FIRE1 )
571  {
572    this->hideStats();
573  }
[8623]574}
[8147]575
[8623]576void MultiplayerTeamDeathmatch::onButtonCancel( )
577{
578  this->bShowTeamChange = false;
579}
[8147]580
581
582
[8623]583/**
584 * this method is called by NetworkGameManger when he recieved a chat message
585 * @param userId senders user id
586 * @param message message string
587 * @param messageType some int
588 */
589void MultiplayerTeamDeathmatch::handleChatMessage( int userId, const std::string & message, int messageType )
590{
591  std::string name = "unknown";
[8717]592
[8623]593  if ( PlayerStats::getStats( userId ) )
594  {
595    name = PlayerStats::getStats( userId )->getNickName();
596  }
[8717]597
[8708]598  PRINTF(0)("CHATMESSAGE %s (%d): %s\n", name.c_str(), userId, message.c_str() );
599  notifier->pushNotifyMessage(name + ": " + message);
[8623]600}
[8147]601
[8708]602void MultiplayerTeamDeathmatch::onInputEnter( const std::string & text )
603{
604  EventHandler::getInstance()->popState();
[8717]605  input->breakMouseFocus();
[8708]606  input->hide();
607  input->setText("");
[8623]608
[8708]609  std::string command = text;
[8717]610
[8708]611  //HACK insert " in say commands so user doesn't have to type them
612  if ( command.length() >= 4 && command[0] == 's' && command[1] == 'a' && command[2] == 'y' && command[3] == ' ' )
613  {
614    command.insert( 4, "\"" );
615    command = command + "\"";
616  }
[8623]617
[8708]618  OrxShell::ShellCommand::execute( command );
619}
[8623]620
[8802]621/**
622 * show table with frags
623 */
624void MultiplayerTeamDeathmatch::showStats( )
625{
626  EventHandler::getInstance()->pushState( ES_MENU );
627  statsBox = new OrxGui::GLGuiBox();
628  statsBox->setAbsCoor2D( 300, 100 );
[9008]629
[8802]630  this->table = new OrxGui::GLGuiTable(0,0);
[8708]631
[8802]632  statsBox->pack( this->table );
[8708]633
[8802]634  statsBox->showAll();
635}
[8708]636
[8802]637/**
638 * hide table with frags
639 */
640void MultiplayerTeamDeathmatch::hideStats( )
641{
642    if ( statsBox )
643    {
644      delete statsBox;
645      statsBox = NULL;
646    }
[9008]647
[8802]648    EventHandler::getInstance()->popState();
649}
650
651/**
652 * fill stats table with values
653 */
654void MultiplayerTeamDeathmatch::tickStatsTable( )
655{
656  if ( !this->statsBox )
657    return;
658
659  std::vector<std::string> headers;
660  headers.push_back("Red Team");
661  headers.push_back("");
662  headers.push_back("");
663  headers.push_back("Blue Team");
664  headers.push_back("");
665  this->table->setHeader(headers);
[9008]666
[8802]667  std::map<int,std::string> fragsTeam0;
668  std::map<int,std::string> fragsTeam1;
[9008]669
[8802]670  const std::list<BaseObject*> * list = ClassList::getList( CL_PLAYER_STATS );
[9008]671
[8802]672  if ( !list )
673    return;
[9008]674
[8802]675  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
676  {
677    PlayerStats & stats = *dynamic_cast<PlayerStats*>(*it);
[9008]678
[8802]679    if ( stats.getTeamId() == 0 || stats.getTeamId() == 1 )
680    {
681      if ( stats.getTeamId() == 0 )
682        fragsTeam0[stats.getScore()] = stats.getNickName();
683      else
684        fragsTeam1[stats.getScore()] = stats.getNickName();
685    }
686  }
[9008]687
[8802]688  char st[10];
689  int i = 0;
[9008]690
691
[8802]692  i = 2;
693  for ( std::map<int,std::string>::const_iterator it = fragsTeam0.begin(); it != fragsTeam0.end(); it++ )
694  {
695    this->table->setEntry( 0, i, it->second );
696    snprintf( st, 10, "%d", it->first );
697    this->table->setEntry( 1, i, st );
698    this->table->setEntry( 2, i, "" );
699    i++;
700  }
[9008]701
[8802]702  i = 2;
703  for ( std::map<int,std::string>::const_iterator it = fragsTeam1.begin(); it != fragsTeam1.end(); it++ )
704  {
705    this->table->setEntry( 3, i, it->second );
706    snprintf( st, 10, "%d", it->first );
707    this->table->setEntry( 4, i, st );
708    i++;
709  }
710}
711
712/**
713 * this function is called when a player kills another one or himself
[9008]714 * @param killedUserId
715 * @param userId
[8802]716 */
[9008]717void MultiplayerTeamDeathmatch::onKill( WorldEntity * victim, WorldEntity * killer )
[8802]718{
[9008]719  if ( !victim )
720    return;
721  if ( !killer )
722    return;
[8802]723 
[9008]724  int killerUserId = killer->getOwner();
725  int victimUserId = victim->getOwner();
726
727  PlayerStats & victimStats = *PlayerStats::getStats( victimUserId );
728  PlayerStats & killerStats = *PlayerStats::getStats( killerUserId );
[8802]729 
[9008]730  if ( killerStats.getPlayable() != killer || victimStats.getPlayable() != victim )
731    return;
732
733  //check for suicide
734  if ( killerUserId != victimUserId )
735  {
736    //check for teamkill
737    if ( victimStats.getTeamId() != killerStats.getTeamId() )
738    {
739      killerStats.setScore( killerStats.getScore() + 1 );
740    }
741    else
742    {
743      killerStats.setScore( killerStats.getScore() - 1 );
744    }
745  }
[8802]746  else
[9008]747    killerStats.setScore( killerStats.getScore() - 1 );
748
749  if ( victimUserId == SharedNetworkData::getInstance()->getHostID() )
[8802]750  {
751    this->bLocalPlayerDead = true;
752    this->showStats();
753  }
[9008]754
755  this->respawnPlayable( victimStats.getPlayable(), victimStats.getTeamId(), 3.0f );
[8802]756}
757
758/**
759 * this function is called on player respawn
[9008]760 * @param userId
[8802]761 */
762void MultiplayerTeamDeathmatch::onRespawn( int userId )
763{
764  if ( userId == SharedNetworkData::getInstance()->getHostID() )
765  {
766    this->bLocalPlayerDead = false;
767    this->hideStats();
768  }
769}
770
771/**
772 * this function is called on player respawn
[9008]773 * @param we
[8802]774 */
775void MultiplayerTeamDeathmatch::registerSpawn( WorldEntity * we )
776{
777  onRespawn( we->getOwner() );
778}
779
[9008]780
781void MultiplayerTeamDeathmatch::respawnPlayable( Playable * playable, int teamId, float delay )
782{
783  const std::list<BaseObject*> * list = ClassList::getList( CL_SPAWNING_POINT );
784
785  assert( list );
786
787  std::vector<SpawningPoint*> spList;
788
789  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
790  {
791    SpawningPoint * sp = dynamic_cast<SpawningPoint*>(*it);
792
793    if ( sp->getTeamId() == teamId )
794      spList.push_back( sp );
795  }
796
797  if ( spList.size() == 0 )
798  {
799    for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
800    {
801      SpawningPoint * sp = dynamic_cast<SpawningPoint*>(*it);
802
803      if ( sp->getTeamId() < 0 )
804        spList.push_back( sp );
805    }
806  }
807
808  assert( spList.size() != 0 );
809
810  int n = (int)((float)spList.size() * (float)rand()/(float)RAND_MAX);
811
812  spList[n]->pushEntity( playable, delay );
813}
814
Note: See TracBrowser for help on using the repository browser.