Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

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

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