Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/util/multiplayer_team_deathmatch.cc @ 10129

Last change on this file since 10129 was 10114, checked in by patrick, 17 years ago

merged network back to trunk

File size: 20.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"
[7034]26
[7044]27#include "player.h"
28#include "playable.h"
[7101]29#include "space_ships/space_ship.h"
[7039]30
[7116]31
[7101]32#include "shared_network_data.h"
[7116]33#include "terrain.h"
34#include "space_ships/space_ship.h"
[7044]35
[8068]36#include "network_game_manager.h"
[7101]37
[8147]38#include "event_handler.h"
[8068]39
[8147]40#include "glgui.h"
41
42#include "story_entity.h"
43
[8708]44#include "shell_command.h"
[8147]45
[8802]46#include "spawning_point.h"
[8708]47
[10114]48#include "creatures/fps_player.h"
[8802]49
[10114]50ObjectListDefinition(MultiplayerTeamDeathmatch);
[9869]51CREATE_FACTORY(MultiplayerTeamDeathmatch);
[7034]52/**
53 * constructor
54 */
[7035]55MultiplayerTeamDeathmatch::MultiplayerTeamDeathmatch(const TiXmlElement* root)
[9869]56    : NetworkGameRules(root)
[7035]57{
[9869]58  this->registerObject(this, MultiplayerTeamDeathmatch::_objectList);
[7034]59
[7037]60  this->bLocalPlayerDead = false;
61  this->deathTimeout = 10.0f;     // 5 seconds
[7082]62  this->timeout = 0.0f;
[8068]63  this->numTeams = 2;
64  this->currentGameState = GAMESTATE_PRE_GAME;
[9008]65  this->gameStateTimer = 3.0f;
[8623]66  this->bShowTeamChange = false;
[8717]67
[8147]68  this->box = NULL;
[8802]69  this->table = NULL;
70  this->statsBox = NULL;
[7040]71
[7044]72  this->localPlayer = State::getPlayer();
73
[7035]74  if( root != NULL)
75    this->loadParams(root);
[8717]76
[8623]77  subscribeEvent( ES_GAME, SDLK_o );
[8708]78  subscribeEvent( ES_GAME, SDLK_TAB );
[8802]79  subscribeEvent( ES_GAME, SDLK_F1 );
80  subscribeEvent( ES_MENU, KeyMapper::PEV_FIRE1 );
[9008]81
[8708]82  this->input = new OrxGui::GLGuiInputLine();
83  this->input->setAbsCoor2D(180, 5);
[9406]84  this->input->enterPushed.connect(this, &MultiplayerTeamDeathmatch::onInputEnter);
[7035]85}
86
[7034]87/**
88 * decontsructor
89 */
90MultiplayerTeamDeathmatch::~MultiplayerTeamDeathmatch()
[7044]91{
[8623]92  unsubscribeEvent( ES_GAME, SDLK_o );
[8708]93  unsubscribeEvent( ES_GAME, SDLK_TAB );
[8802]94  unsubscribeEvent( ES_GAME, SDLK_F1 );
95  unsubscribeEvent( ES_MENU, KeyMapper::PEV_FIRE1 );
[9008]96
[8708]97  if ( this->input )
98  {
99    delete this->input;
100    this->input = NULL;
101  }
[7044]102}
[7034]103
104
105
106void MultiplayerTeamDeathmatch::loadParams(const TiXmlElement* root)
[7035]107{
[7040]108  GameRules::loadParams(root) ;
[7037]109
110  LoadParam(root, "death-penalty-timeout", this, MultiplayerTeamDeathmatch, setDeathPenaltyTimeout)
[9869]111  .describe("sets the time in seconds a player has to wait for respawn");
[7037]112
113  LoadParam(root, "max-kills", this, MultiplayerTeamDeathmatch, setMaxKills)
[9869]114  .describe("sets the maximal kills for winning condition");
[7039]115
[8068]116  LoadParam(root, "num-teams", this, MultiplayerTeamDeathmatch, setNumTeams)
[9869]117  .describe("sets number of teams");
[7039]118
[7035]119}
120
121
122/**
123 * time tick
124 * @param dt time
125 */
126void MultiplayerTeamDeathmatch::tick(float dt)
[7037]127{
[8802]128  tickStatsTable();
[8147]129  //on client side hostId is -1 until hanshake finished
130  if ( SharedNetworkData::getInstance()->getHostID() < 0 )
131    return;
[8717]132
[8623]133  if ( currentGameState == GAMESTATE_PRE_GAME || currentGameState == GAMESTATE_GAME )
[8147]134  {
[9656]135    if ( PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() ) &&
136         box == NULL &&
137         (PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPreferedTeamId() == TEAM_NOTEAM || bShowTeamChange )
[8717]138
[8147]139       )
140    {
141      EventHandler::getInstance()->pushState( ES_MENU );
[8717]142
[8147]143      OrxGui::GLGuiHandler::getInstance()->activateCursor();
[8717]144
[8147]145      box = new OrxGui::GLGuiBox();
146      box->setAbsCoor2D( 300, 100 );
[8717]147
[10114]148      OrxGui::GLGuiPushButton * buttonSpectator = new OrxGui::GLGuiPushButton("Spectator");
149      box->pack( buttonSpectator );
150      buttonSpectator->released.connect(this, &MultiplayerTeamDeathmatch::onButtonSpectator);
[8717]151
[10114]152      OrxGui::GLGuiPushButton * buttonRandom = new OrxGui::GLGuiPushButton("Random");
153      box->pack( buttonRandom );
154      buttonRandom->released.connect(this, &MultiplayerTeamDeathmatch::onButtonRandom);
[8717]155
[10114]156      OrxGui::GLGuiPushButton * buttonTeam0 = new OrxGui::GLGuiPushButton("Blue Team");
157      box->pack( buttonTeam0 );
158      buttonTeam0->released.connect(this, &MultiplayerTeamDeathmatch::onButtonTeam0);
[8717]159
[10114]160      OrxGui::GLGuiPushButton * buttonTeam1 = new OrxGui::GLGuiPushButton("Red Team");
161      box->pack( buttonTeam1 );
162      buttonTeam1->released.connect(this, &MultiplayerTeamDeathmatch::onButtonTeam1);
[8717]163
[8623]164      if ( bShowTeamChange )
165      {
166        OrxGui::GLGuiPushButton * buttonCancel = new OrxGui::GLGuiPushButton("Cancel");
167        box->pack( buttonCancel );
[9406]168        buttonCancel->released.connect(this, &MultiplayerTeamDeathmatch::onButtonCancel);
[8623]169      }
[8717]170
[8147]171      OrxGui::GLGuiPushButton * buttonExit = new OrxGui::GLGuiPushButton("Exit");
172      box->pack( buttonExit );
[9406]173      buttonExit->released.connect(this, &MultiplayerTeamDeathmatch::onButtonExit);
[8717]174
[8147]175      box->showAll();
176    }
177  }
178
[9869]179  //   if( PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() ) )
180  //   {
181  //     PRINTF(0)("prefered team id: %i, noteam: %i\n", PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPreferedTeamId(), TEAM_NOTEAM);
182  //   }
[9656]183
184  // check if the menu should be removed and the game state should be entered
185  if ( box != NULL &&
186       PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() ) &&
187       PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPreferedTeamId() != TEAM_NOTEAM &&
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
[9494]206  if ( SharedNetworkData::getInstance()->isClient() || SharedNetworkData::getInstance()->isProxyServerActive())
[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  {
260  }
261}
[7035]262
[7039]263
[7035]264/**
265 * check the game rules for consistency
266 */
267void MultiplayerTeamDeathmatch::checkGameRules()
[7039]268{
[9494]269  if ( SharedNetworkData::getInstance()->isClient() || SharedNetworkData::getInstance()->isProxyServerActive())
[8068]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 )
[9869]294    return ObjectListBase::retrieveIdentity("Spectator");
[8717]295
[8147]296  if ( team == 0 || team == 1 )
[10114]297    return ObjectListBase::retrieveIdentity("FPSPlayer");
[8717]298
[8147]299  assert( false );
[8068]300}
[7101]301
[9656]302
[9869]303std::string MultiplayerTeamDeathmatch::getPlayableModelFileName( int userId, int team, const 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
[10114]310  {
[8147]311    return "";
[10114]312  }
[8068]313}
314
[9869]315std::string MultiplayerTeamDeathmatch::getPlayableModelTextureFileName( int userId, int team, const ClassID& classId )
[9235]316{
[10114]317  if ( team == 0 || team == 1 )
[9235]318  {
319    if ( team == 0 )
[10114]320      return "doom_guy.png";
[9235]321    else
[10114]322      return "male_fiend.pcx";
[9235]323  }
[9406]324
[9235]325  return "";
326}
327
[9869]328float MultiplayerTeamDeathmatch::getPlayableScale( int userId, int team, const ClassID& classId )
[9235]329{
[10114]330  if ( classId == FPSPlayer::staticClassID() )
[9235]331  {
332    return 10.0f;
333  }
[9406]334
[9235]335  return 1.0f;
336}
337
[8068]338/**
339 * calculate team score
340 */
341void MultiplayerTeamDeathmatch::calculateTeamScore( )
342{
343  teamScore.clear();
[8717]344
[8068]345  for ( int i = 0; i<numTeams; i++ )
346    teamScore[i] = 0;
[8717]347
[9869]348  for (ObjectList<PlayerStats>::const_iterator it = PlayerStats::objectList().begin();
349       it != PlayerStats::objectList().end();
350       ++it)
[7039]351  {
[9869]352    PlayerStats & stats = *(*it);
[8068]353
354    if ( stats.getTeamId() >= 0 )
355    {
356      teamScore[stats.getTeamId()] += stats.getScore();
357    }
[7039]358  }
[8068]359}
360
361/**
362 * get team for player who choose to join random team
363 * @return smallest team
364 */
365int MultiplayerTeamDeathmatch::getRandomTeam( )
366{
367  std::map<int,int> playersInTeam;
[8717]368
[8068]369  for ( int i = 0; i<numTeams; i++ )
370    playersInTeam[i] = 0;
[8717]371
[9869]372  for (ObjectList<PlayerStats>::const_iterator it = PlayerStats::objectList().begin();
373       it != PlayerStats::objectList().end();
374       ++it)
[7039]375  {
[9869]376    PlayerStats & stats = *(*it);
[8068]377
378    if ( stats.getTeamId() >= 0 )
379    {
380      playersInTeam[stats.getTeamId()]++;
381    }
[7039]382  }
[8717]383
384
[8068]385  int minPlayers = 0xFFFF;
386  int minTeam = -1;
[8717]387
[8068]388  for ( int i = 0; i<numTeams; i++ )
389  {
390    if ( playersInTeam[i] < minPlayers )
391    {
392      minTeam = i;
393      minPlayers = playersInTeam[i];
394    }
395  }
[8717]396
[8068]397  assert( minTeam != -1 );
[8717]398
[8068]399  return minTeam;
400}
[7101]401
[8068]402void MultiplayerTeamDeathmatch::nextGameState( )
403{
404  if ( currentGameState == GAMESTATE_PRE_GAME )
405  {
406    NetworkGameManager::getInstance()->setGameState( GAMESTATE_GAME );
[8717]407
[8068]408    return;
409  }
[8717]410
[8068]411  if ( currentGameState == GAMESTATE_GAME )
412  {
413    NetworkGameManager::getInstance()->setGameState( GAMESTATE_POST_GAME );
[8717]414
[8068]415    return;
416  }
[8717]417
[8068]418  if ( currentGameState == GAMESTATE_POST_GAME )
419  {
[9235]420    //State::getCurrentStoryEntity()->stop();
[8802]421    this->bShowTeamChange = false;
[8717]422
[8068]423    return;
424  }
425}
[7118]426
[9656]427/**
428 *  this handles team changes but only on the master server
429 */
[8068]430void MultiplayerTeamDeathmatch::handleTeamChanges( )
431{
[9869]432  for (ObjectList<PlayerStats>::const_iterator it = PlayerStats::objectList().begin();
433       it != PlayerStats::objectList().end();
434       ++it)
[7116]435  {
[9869]436    PlayerStats & stats = *(*it);
[7118]437
[8068]438    if ( stats.getTeamId() != stats.getPreferedTeamId() )
[7116]439    {
[8147]440      if ( stats.getPreferedTeamId() == TEAM_SPECTATOR || ( stats.getPreferedTeamId() >= 0 && stats.getPreferedTeamId() < numTeams ) )
[7116]441      {
[9656]442        teamChange( stats.getAssignedUserId() );
[7116]443      }
444    }
445  }
[8717]446
[8068]447  //now serve player who want join a random team
[9869]448  for (ObjectList<PlayerStats>::const_iterator it = PlayerStats::objectList().begin();
449       it != PlayerStats::objectList().end();
450       ++it)
[8068]451  {
[9869]452    PlayerStats & stats = *(*it);
[7101]453
[8068]454    if ( stats.getTeamId() != stats.getPreferedTeamId() )
[7101]455    {
[8068]456      if ( stats.getPreferedTeamId() == TEAM_RANDOM )
[7101]457      {
[8147]458        stats.setPreferedTeamId( getRandomTeam() );
[9656]459        teamChange( stats.getAssignedUserId() );
[7101]460      }
461    }
462  }
[8068]463}
[7101]464
[9656]465
466
467/**
468 * changes the team
469 * @param userId the user changing team (userId)
470 */
[8068]471void MultiplayerTeamDeathmatch::teamChange( int userId )
472{
473  assert( PlayerStats::getStats( userId ) );
474  PlayerStats & stats = *(PlayerStats::getStats( userId ));
[8717]475
[8147]476  stats.setTeamId( stats.getPreferedTeamId() );
[8717]477
[8147]478  Playable * oldPlayable = stats.getPlayable();
[8717]479
480
[9656]481  ClassID       playableClassId  = getPlayableClassId( userId, stats.getPreferedTeamId() );
482  std::string   playableModel    = getPlayableModelFileName( userId, stats.getPreferedTeamId(), playableClassId );
483  std::string   playableTexture  = getPlayableModelTextureFileName( userId, stats.getPreferedTeamId(), playableClassId );
484  float         playableScale    = getPlayableScale( userId, stats.getPreferedTeamId(), playableClassId );
[8717]485
[8147]486  BaseObject * bo = Factory::fabricate( playableClassId );
[8717]487
[8147]488  assert( bo != NULL );
[10114]489  assert( bo->isA( Playable::staticClassID() ) );
[8717]490
[8147]491  Playable & playable = *(dynamic_cast<Playable*>(bo));
[8717]492
[10114]493  PRINTF(0)("%s %s %f\n", playableModel.c_str(), playableTexture.c_str(), playableScale );
494 
[9235]495  playable.loadMD2Texture( playableTexture );
496  playable.loadModel( playableModel, playableScale );
[8147]497  playable.setOwner( userId );
498  playable.setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
499  playable.setSynchronized( true );
[8717]500
[8147]501  stats.setPlayableClassId( playableClassId );
502  stats.setPlayableUniqueId( playable.getUniqueID() );
503  stats.setModelFileName( playableModel );
[9656]504  stats.setTeamId( stats.getPreferedTeamId() );
[8717]505
[9656]506  playable.setTeam(stats.getPreferedTeamId());
507
508
[9008]509  this->respawnPlayable( &playable, stats.getPreferedTeamId(), 0.0f );
510
[8147]511  if ( oldPlayable )
512  {
513    delete oldPlayable;
514  }
[7039]515}
[7035]516
[9656]517
[8147]518void MultiplayerTeamDeathmatch::onButtonExit( )
519{
520  State::getCurrentStoryEntity()->stop();
[8623]521  this->bShowTeamChange = false;
[8147]522}
[7035]523
[8147]524void MultiplayerTeamDeathmatch::onButtonRandom( )
525{
526  NetworkGameManager::getInstance()->prefereTeam( TEAM_RANDOM );
[8623]527  this->bShowTeamChange = false;
[8147]528}
[7035]529
[8147]530void MultiplayerTeamDeathmatch::onButtonTeam0( )
531{
532  NetworkGameManager::getInstance()->prefereTeam( 0 );
[8623]533  this->bShowTeamChange = false;
[8147]534}
[7035]535
[8147]536void MultiplayerTeamDeathmatch::onButtonTeam1( )
537{
538  NetworkGameManager::getInstance()->prefereTeam( 1 );
[8623]539  this->bShowTeamChange = false;
[8147]540}
[7035]541
[8147]542void MultiplayerTeamDeathmatch::onButtonSpectator( )
543{
544  NetworkGameManager::getInstance()->prefereTeam( TEAM_SPECTATOR );
[8623]545  this->bShowTeamChange = false;
[8147]546}
[7035]547
[8147]548void MultiplayerTeamDeathmatch::assignPlayable( )
549{
550  if ( PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() ) )
551    PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPlayable();
552}
553
[9656]554
555/**
556 * function that processes events from the handler
557 * @param event: the event
558 * @todo replace SDLK_o with something from KeyMapper
559 */
[8623]560void MultiplayerTeamDeathmatch::process( const Event & event )
561{
562  if ( event.type == SDLK_o )
563  {
564    if ( event.bPressed )
565      this->bShowTeamChange = true;
[9869]566  }
567  else if ( event.type == SDLK_F1 )
[8802]568  {
[9059]569    if ( this->statsBox && !this->bLocalPlayerDead && event.bPressed )
570    {
[9656]571      PRINTF(5)("hide stats\n");
[9059]572      this->hideStats();
573    }
[9110]574    else if ( !this->statsBox && event.bPressed )
[8802]575    {
[9656]576      PRINTF(5)("show stats\n");
[8802]577      this->showStats();
578    }
[8623]579  }
[8708]580  else if ( event.type == SDLK_TAB )
581  {
[9008]582    if ( currentGameState == GAMESTATE_GAME && event.bPressed && !EventHandler::getInstance()->isPressed( SDLK_RALT ) && !EventHandler::getInstance()->isPressed( SDLK_LALT ) )
[8708]583    {
584      EventHandler::getInstance()->pushState( ES_MENU );
585      OrxGui::GLGuiHandler::getInstance()->activateCursor();
586      OrxGui::GLGuiHandler::getInstance()->deactivateCursor();
587      input->show();
[8717]588      input->giveMouseFocus();
[8708]589      input->setText("say ");
590    }
591  }
[8802]592  else if ( this->bLocalPlayerDead && statsBox && event.type == KeyMapper::PEV_FIRE1 )
593  {
594    this->hideStats();
595  }
[8623]596}
[8147]597
[8623]598void MultiplayerTeamDeathmatch::onButtonCancel( )
599{
600  this->bShowTeamChange = false;
601}
[8147]602
603
604
[8623]605/**
606 * this method is called by NetworkGameManger when he recieved a chat message
607 * @param userId senders user id
608 * @param message message string
609 * @param messageType some int
610 */
611void MultiplayerTeamDeathmatch::handleChatMessage( int userId, const std::string & message, int messageType )
612{
613  std::string name = "unknown";
[8717]614
[8623]615  if ( PlayerStats::getStats( userId ) )
616  {
617    name = PlayerStats::getStats( userId )->getNickName();
618  }
[8717]619
[8708]620  PRINTF(0)("CHATMESSAGE %s (%d): %s\n", name.c_str(), userId, message.c_str() );
[9059]621  State::getPlayer()->hud().notifyUser(name + ": " + message);
[8623]622}
[8147]623
[8708]624void MultiplayerTeamDeathmatch::onInputEnter( const std::string & text )
625{
626  EventHandler::getInstance()->popState();
[8717]627  input->breakMouseFocus();
[8708]628  input->hide();
629  input->setText("");
[8623]630
[8708]631  std::string command = text;
[8717]632
[8708]633  //HACK insert " in say commands so user doesn't have to type them
634  if ( command.length() >= 4 && command[0] == 's' && command[1] == 'a' && command[2] == 'y' && command[3] == ' ' )
635  {
636    command.insert( 4, "\"" );
637    command = command + "\"";
638  }
[8623]639
[8708]640  OrxShell::ShellCommand::execute( command );
641}
[8623]642
[8802]643/**
644 * show table with frags
645 */
646void MultiplayerTeamDeathmatch::showStats( )
647{
648  statsBox = new OrxGui::GLGuiBox();
[9110]649  statsBox->setAbsCoor2D( 100, 100 );
[9008]650
[9110]651  this->table = new OrxGui::GLGuiTable(10,5);
[8708]652
[8802]653  statsBox->pack( this->table );
[8708]654
[8802]655  statsBox->showAll();
656}
[8708]657
[8802]658/**
659 * hide table with frags
660 */
661void MultiplayerTeamDeathmatch::hideStats( )
662{
[9869]663  if ( statsBox )
664  {
665    delete statsBox;
666    statsBox = NULL;
667  }
[8802]668}
669
670/**
671 * fill stats table with values
672 */
673void MultiplayerTeamDeathmatch::tickStatsTable( )
674{
675  if ( !this->statsBox )
676    return;
677
678  std::vector<std::string> headers;
[9110]679  headers.push_back("Blue Team");
[8802]680  headers.push_back("");
681  headers.push_back("");
[9110]682  headers.push_back("Red Team");
[8802]683  headers.push_back("");
684  this->table->setHeader(headers);
[9008]685
[9110]686  ScoreList scoreList = PlayerStats::getScoreList();
[9008]687
[8802]688  char st[10];
689  int i = 0;
[9406]690
[8802]691  i = 2;
[9110]692  for ( TeamScoreList::const_iterator it = scoreList[0].begin(); it != scoreList[0].end(); it++ )
[8802]693  {
[9110]694    this->table->setEntry( i, 0, it->name );
695    snprintf( st, 10, "%d", it->score );
696    this->table->setEntry( i, 1, st );
697    this->table->setEntry( i, 2, "" );
[8802]698    i++;
699  }
[9008]700
[8802]701  i = 2;
[9110]702  for ( TeamScoreList::const_iterator it = scoreList[1].begin(); it != scoreList[1].end(); it++ )
[8802]703  {
[9110]704    this->table->setEntry( i, 3, it->name );
705    snprintf( st, 10, "%d", it->score );
706    this->table->setEntry( i, 4, st );
[8802]707    i++;
708  }
[9110]709
[8802]710}
711
712/**
713 * this function is called when a player kills another one or himself
[9008]714 * @param killedUserId
715 * @param userId
[8802]716 */
[9008]717void MultiplayerTeamDeathmatch::onKill( WorldEntity * victim, WorldEntity * killer )
[8802]718{
[9008]719  if ( !victim )
[9235]720  {
721    PRINTF(0)("victim == NULL\n");
[9008]722    return;
[9235]723  }
[9008]724  if ( !killer )
[9235]725  {
726    PRINTF(0)("killer == NULL\n");
[9008]727    return;
[9235]728  }
[9406]729
[9008]730  int killerUserId = killer->getOwner();
731  int victimUserId = victim->getOwner();
732
[9406]733  PRINTF(0)("%d %d %x %x %s %s\n", killerUserId, victimUserId, killer, victim, killer->getClassCName(), victim->getClassCName());
734
[9008]735  PlayerStats & victimStats = *PlayerStats::getStats( victimUserId );
736  PlayerStats & killerStats = *PlayerStats::getStats( killerUserId );
[9406]737
[9656]738  if ( killerStats.getPlayable() == NULL || victimStats.getPlayable() == NULL)
[9235]739  {
[9656]740    PRINTF(0)("killerStats.getPlayable() != NULL || victimStats.getPlayable() != NULL\n");
[9235]741    PRINTF(0)("%x %x %x %x\n", killerStats.getPlayable(), killer, victimStats.getPlayable(), victim );
742    PRINTF(0)("%d %d %d %d\n", killerStats.getPlayable()->getUniqueID(), killer->getUniqueID(), victimStats.getPlayable()->getUniqueID(), victim->getUniqueID() );
[9008]743    return;
[9235]744  }
[9008]745
746  //check for suicide
747  if ( killerUserId != victimUserId )
748  {
749    //check for teamkill
750    if ( victimStats.getTeamId() != killerStats.getTeamId() )
751    {
752      killerStats.setScore( killerStats.getScore() + 1 );
753    }
754    else
755    {
756      killerStats.setScore( killerStats.getScore() - 1 );
757    }
758  }
[8802]759  else
[9008]760    killerStats.setScore( killerStats.getScore() - 1 );
761
762  if ( victimUserId == SharedNetworkData::getInstance()->getHostID() )
[8802]763  {
764    this->bLocalPlayerDead = true;
765    this->showStats();
766  }
[9008]767
768  this->respawnPlayable( victimStats.getPlayable(), victimStats.getTeamId(), 3.0f );
[8802]769}
770
771/**
772 * this function is called on player respawn
[9008]773 * @param userId
[8802]774 */
775void MultiplayerTeamDeathmatch::onRespawn( int userId )
776{
777  if ( userId == SharedNetworkData::getInstance()->getHostID() )
778  {
779    this->bLocalPlayerDead = false;
780    this->hideStats();
781  }
782}
783
784/**
785 * this function is called on player respawn
[9008]786 * @param we
[8802]787 */
788void MultiplayerTeamDeathmatch::registerSpawn( WorldEntity * we )
789{
790  onRespawn( we->getOwner() );
791}
792
[9008]793
[9656]794/**
795 * respawns a playable in the world via spawning points
796 * @param playable the playable to respawn
797 * @param teamId the teamId to use
798 * @param delay time delay for delayed spawning
799 */
[9008]800void MultiplayerTeamDeathmatch::respawnPlayable( Playable * playable, int teamId, float delay )
801{
802
803  std::vector<SpawningPoint*> spList;
804
[9869]805  for (ObjectList<SpawningPoint>::const_iterator it = SpawningPoint::objectList().begin();
806       it != SpawningPoint::objectList().end();
807       ++it)
[9008]808  {
[9869]809    SpawningPoint * sp = (*it);
[9008]810
811    if ( sp->getTeamId() == teamId )
812      spList.push_back( sp );
813  }
814
815  if ( spList.size() == 0 )
816  {
[9869]817    for (ObjectList<SpawningPoint>::const_iterator it = SpawningPoint::objectList().begin();
818         it != SpawningPoint::objectList().end();
819         ++it)
[9008]820    {
[9869]821      SpawningPoint * sp = (*it);
[9008]822
823      if ( sp->getTeamId() < 0 )
824        spList.push_back( sp );
825    }
826  }
827
828  assert( spList.size() != 0 );
829
830  int n = (int)((float)spList.size() * (float)rand()/(float)RAND_MAX);
831
832  spList[n]->pushEntity( playable, delay );
833}
834
[9110]835
Note: See TracBrowser for help on using the repository browser.