Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/presentation/src/util/multiplayer_team_deathmatch.cc @ 9141

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

new model for team 1

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