Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/proxy/src/util/multiplayer_team_deathmatch.cc @ 9498

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

set team id is invoked on team change

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