Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10025 was 9869, checked in by bensch, 18 years ago

orxonox/trunk: merged the new_class_id branche back to the trunk.
merged with command:
svn merge https://svn.orxonox.net/orxonox/branches/new_class_id trunk -r9683:HEAD
no conflicts… puh..

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