Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

mulitplayer distances

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