Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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