Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9502 was 9500, checked in by bensch, 18 years ago

compiles again, the Playables should now be able to choose their design per team

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
[9500]491  ClassID     playableClassId = getPlayableClassId( userId, stats.getPreferedTeamId() );
[8147]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 );
[9500]505  playable.setTeam(stats.getPreferedTeamId());
[8147]506  playable.setOwner( userId );
507  playable.setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
508  playable.setSynchronized( true );
[8717]509
[8147]510  stats.setTeamId( stats.getPreferedTeamId() );
511  stats.setPlayableClassId( playableClassId );
512  stats.setPlayableUniqueId( playable.getUniqueID() );
513  stats.setModelFileName( playableModel );
[8717]514
[9008]515  this->respawnPlayable( &playable, stats.getPreferedTeamId(), 0.0f );
516
[8147]517  if ( oldPlayable )
518  {
519    //if ( userId == SharedNetworkData::getInstance()->getHostID() )
520    //  State::getPlayer()->setPlayable( NULL );
521    delete oldPlayable;
522  }
[7039]523}
[7035]524
[8147]525void MultiplayerTeamDeathmatch::onButtonExit( )
526{
527  State::getCurrentStoryEntity()->stop();
[8623]528  this->bShowTeamChange = false;
[8147]529}
[7035]530
[8147]531void MultiplayerTeamDeathmatch::onButtonRandom( )
532{
533  NetworkGameManager::getInstance()->prefereTeam( TEAM_RANDOM );
[8623]534  this->bShowTeamChange = false;
[8147]535}
[7035]536
[8147]537void MultiplayerTeamDeathmatch::onButtonTeam0( )
538{
539  NetworkGameManager::getInstance()->prefereTeam( 0 );
[8623]540  this->bShowTeamChange = false;
[8147]541}
[7035]542
[8147]543void MultiplayerTeamDeathmatch::onButtonTeam1( )
544{
545  NetworkGameManager::getInstance()->prefereTeam( 1 );
[8623]546  this->bShowTeamChange = false;
[8147]547}
[7035]548
[8147]549void MultiplayerTeamDeathmatch::onButtonSpectator( )
550{
551  NetworkGameManager::getInstance()->prefereTeam( TEAM_SPECTATOR );
[8623]552  this->bShowTeamChange = false;
[8147]553}
[7035]554
[8147]555void MultiplayerTeamDeathmatch::assignPlayable( )
556{
557  if ( PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() ) )
558    PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPlayable();
559}
560
[8623]561  /**
562   * function that processes events from the handler
563   * @param event: the event
564   * @todo replace SDLK_o with something from KeyMapper
565   */
566void MultiplayerTeamDeathmatch::process( const Event & event )
567{
568  if ( event.type == SDLK_o )
569  {
570    if ( event.bPressed )
571      this->bShowTeamChange = true;
[8802]572  } else if ( event.type == SDLK_F1 )
573  {
[9059]574    if ( this->statsBox && !this->bLocalPlayerDead && event.bPressed )
575    {
576      PRINTF(0)("hide stats\n");
577      this->hideStats();
578    }
[9110]579    else if ( !this->statsBox && event.bPressed )
[8802]580    {
581      PRINTF(0)("show stats\n");
582      this->showStats();
583    }
[8623]584  }
[8708]585  else if ( event.type == SDLK_TAB )
586  {
[9008]587    if ( currentGameState == GAMESTATE_GAME && event.bPressed && !EventHandler::getInstance()->isPressed( SDLK_RALT ) && !EventHandler::getInstance()->isPressed( SDLK_LALT ) )
[8708]588    {
589      EventHandler::getInstance()->pushState( ES_MENU );
590      OrxGui::GLGuiHandler::getInstance()->activateCursor();
591      OrxGui::GLGuiHandler::getInstance()->deactivateCursor();
592      input->show();
[8717]593      input->giveMouseFocus();
[8708]594      input->setText("say ");
595    }
596  }
[8802]597  else if ( this->bLocalPlayerDead && statsBox && event.type == KeyMapper::PEV_FIRE1 )
598  {
599    this->hideStats();
600  }
[8623]601}
[8147]602
[8623]603void MultiplayerTeamDeathmatch::onButtonCancel( )
604{
605  this->bShowTeamChange = false;
606}
[8147]607
608
609
[8623]610/**
611 * this method is called by NetworkGameManger when he recieved a chat message
612 * @param userId senders user id
613 * @param message message string
614 * @param messageType some int
615 */
616void MultiplayerTeamDeathmatch::handleChatMessage( int userId, const std::string & message, int messageType )
617{
618  std::string name = "unknown";
[8717]619
[8623]620  if ( PlayerStats::getStats( userId ) )
621  {
622    name = PlayerStats::getStats( userId )->getNickName();
623  }
[8717]624
[8708]625  PRINTF(0)("CHATMESSAGE %s (%d): %s\n", name.c_str(), userId, message.c_str() );
[9059]626  State::getPlayer()->hud().notifyUser(name + ": " + message);
[8623]627}
[8147]628
[8708]629void MultiplayerTeamDeathmatch::onInputEnter( const std::string & text )
630{
631  EventHandler::getInstance()->popState();
[8717]632  input->breakMouseFocus();
[8708]633  input->hide();
634  input->setText("");
[8623]635
[8708]636  std::string command = text;
[8717]637
[8708]638  //HACK insert " in say commands so user doesn't have to type them
639  if ( command.length() >= 4 && command[0] == 's' && command[1] == 'a' && command[2] == 'y' && command[3] == ' ' )
640  {
641    command.insert( 4, "\"" );
642    command = command + "\"";
643  }
[8623]644
[8708]645  OrxShell::ShellCommand::execute( command );
646}
[8623]647
[8802]648/**
649 * show table with frags
650 */
651void MultiplayerTeamDeathmatch::showStats( )
652{
653  statsBox = new OrxGui::GLGuiBox();
[9110]654  statsBox->setAbsCoor2D( 100, 100 );
[9008]655
[9110]656  this->table = new OrxGui::GLGuiTable(10,5);
[8708]657
[8802]658  statsBox->pack( this->table );
[8708]659
[8802]660  statsBox->showAll();
661}
[8708]662
[8802]663/**
664 * hide table with frags
665 */
666void MultiplayerTeamDeathmatch::hideStats( )
667{
668    if ( statsBox )
669    {
670      delete statsBox;
671      statsBox = NULL;
672    }
673}
674
675/**
676 * fill stats table with values
677 */
678void MultiplayerTeamDeathmatch::tickStatsTable( )
679{
680  if ( !this->statsBox )
681    return;
682
683  std::vector<std::string> headers;
[9110]684  headers.push_back("Blue Team");
[8802]685  headers.push_back("");
686  headers.push_back("");
[9110]687  headers.push_back("Red Team");
[8802]688  headers.push_back("");
689  this->table->setHeader(headers);
[9008]690
[9110]691  ScoreList scoreList = PlayerStats::getScoreList();
[9008]692
[8802]693  char st[10];
694  int i = 0;
[9406]695
[8802]696  i = 2;
[9110]697  for ( TeamScoreList::const_iterator it = scoreList[0].begin(); it != scoreList[0].end(); it++ )
[8802]698  {
[9110]699    this->table->setEntry( i, 0, it->name );
700    snprintf( st, 10, "%d", it->score );
701    this->table->setEntry( i, 1, st );
702    this->table->setEntry( i, 2, "" );
[8802]703    i++;
704  }
[9008]705
[8802]706  i = 2;
[9110]707  for ( TeamScoreList::const_iterator it = scoreList[1].begin(); it != scoreList[1].end(); it++ )
[8802]708  {
[9110]709    this->table->setEntry( i, 3, it->name );
710    snprintf( st, 10, "%d", it->score );
711    this->table->setEntry( i, 4, st );
[8802]712    i++;
713  }
[9110]714
[8802]715}
716
717/**
718 * this function is called when a player kills another one or himself
[9008]719 * @param killedUserId
720 * @param userId
[8802]721 */
[9008]722void MultiplayerTeamDeathmatch::onKill( WorldEntity * victim, WorldEntity * killer )
[8802]723{
[9008]724  if ( !victim )
[9235]725  {
726    PRINTF(0)("victim == NULL\n");
[9008]727    return;
[9235]728  }
[9008]729  if ( !killer )
[9235]730  {
731    PRINTF(0)("killer == NULL\n");
[9008]732    return;
[9235]733  }
[9406]734
[9008]735  int killerUserId = killer->getOwner();
736  int victimUserId = victim->getOwner();
737
[9406]738  PRINTF(0)("%d %d %x %x %s %s\n", killerUserId, victimUserId, killer, victim, killer->getClassCName(), victim->getClassCName());
739
[9008]740  PlayerStats & victimStats = *PlayerStats::getStats( victimUserId );
741  PlayerStats & killerStats = *PlayerStats::getStats( killerUserId );
[9406]742
[9008]743  if ( killerStats.getPlayable() != killer || victimStats.getPlayable() != victim )
[9235]744  {
745    PRINTF(0)("killerStats.getPlayable() != killer || victimStats.getPlayable() != victim\n");
746    PRINTF(0)("%x %x %x %x\n", killerStats.getPlayable(), killer, victimStats.getPlayable(), victim );
747    PRINTF(0)("%d %d %d %d\n", killerStats.getPlayable()->getUniqueID(), killer->getUniqueID(), victimStats.getPlayable()->getUniqueID(), victim->getUniqueID() );
[9008]748    return;
[9235]749  }
[9008]750
751  //check for suicide
752  if ( killerUserId != victimUserId )
753  {
754    //check for teamkill
755    if ( victimStats.getTeamId() != killerStats.getTeamId() )
756    {
757      killerStats.setScore( killerStats.getScore() + 1 );
758    }
759    else
760    {
761      killerStats.setScore( killerStats.getScore() - 1 );
762    }
763  }
[8802]764  else
[9008]765    killerStats.setScore( killerStats.getScore() - 1 );
766
767  if ( victimUserId == SharedNetworkData::getInstance()->getHostID() )
[8802]768  {
769    this->bLocalPlayerDead = true;
770    this->showStats();
771  }
[9008]772
773  this->respawnPlayable( victimStats.getPlayable(), victimStats.getTeamId(), 3.0f );
[8802]774}
775
776/**
777 * this function is called on player respawn
[9008]778 * @param userId
[8802]779 */
780void MultiplayerTeamDeathmatch::onRespawn( int userId )
781{
782  if ( userId == SharedNetworkData::getInstance()->getHostID() )
783  {
784    this->bLocalPlayerDead = false;
785    this->hideStats();
786  }
787}
788
789/**
790 * this function is called on player respawn
[9008]791 * @param we
[8802]792 */
793void MultiplayerTeamDeathmatch::registerSpawn( WorldEntity * we )
794{
795  onRespawn( we->getOwner() );
796}
797
[9008]798
799void MultiplayerTeamDeathmatch::respawnPlayable( Playable * playable, int teamId, float delay )
800{
801  const std::list<BaseObject*> * list = ClassList::getList( CL_SPAWNING_POINT );
802
803  assert( list );
804
805  std::vector<SpawningPoint*> spList;
806
807  for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
808  {
809    SpawningPoint * sp = dynamic_cast<SpawningPoint*>(*it);
810
811    if ( sp->getTeamId() == teamId )
812      spList.push_back( sp );
813  }
814
815  if ( spList.size() == 0 )
816  {
817    for ( std::list<BaseObject*>::const_iterator it = list->begin(); it != list->end(); it++ )
818    {
819      SpawningPoint * sp = dynamic_cast<SpawningPoint*>(*it);
820
821      if ( sp->getTeamId() < 0 )
822        spList.push_back( sp );
823    }
824  }
825
826  assert( spList.size() != 0 );
827
828  int n = (int)((float)spList.size() * (float)rand()/(float)RAND_MAX);
829
830  spList[n]->pushEntity( playable, delay );
831}
832
[9110]833
Note: See TracBrowser for help on using the repository browser.