Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/terrain/src/util/multiplayer_team_deathmatch.cc @ 9571

Last change on this file since 9571 was 9417, checked in by bensch, 18 years ago

Cleanup after merge

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