Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/network/src/util/multiplayer_team_deathmatch.cc @ 9912

Last change on this file since 9912 was 9912, checked in by rennerc, 17 years ago

still not working

File size: 20.8 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
27#include "player.h"
28#include "playable.h"
29#include "space_ships/space_ship.h"
30
31
32#include "shared_network_data.h"
33#include "terrain.h"
34#include "space_ships/space_ship.h"
35
36#include "network_game_manager.h"
37
38#include "event_handler.h"
39
40#include "glgui.h"
41
42#include "story_entity.h"
43
44#include "shell_command.h"
45
46#include "spawning_point.h"
47
48
49
50#include "class_id_DEPRECATED.h"
51
52ObjectListDefinitionID(MultiplayerTeamDeathmatch, CL_MULTIPLAYER_TEAM_DEATHMATCH);
53CREATE_FACTORY(MultiplayerTeamDeathmatch);
54/**
55 * constructor
56 */
57MultiplayerTeamDeathmatch::MultiplayerTeamDeathmatch(const TiXmlElement* root)
58    : NetworkGameRules(root)
59{
60  this->registerObject(this, MultiplayerTeamDeathmatch::_objectList);
61
62  this->bLocalPlayerDead = false;
63  this->deathTimeout = 10.0f;     // 5 seconds
64  this->timeout = 0.0f;
65  this->numTeams = 2;
66  this->currentGameState = GAMESTATE_PRE_GAME;
67  this->gameStateTimer = 3.0f;
68  this->bShowTeamChange = false;
69
70  this->box = NULL;
71  this->table = NULL;
72  this->statsBox = NULL;
73
74  this->localPlayer = State::getPlayer();
75
76  if( root != NULL)
77    this->loadParams(root);
78
79  subscribeEvent( ES_GAME, SDLK_o );
80  subscribeEvent( ES_GAME, SDLK_TAB );
81  subscribeEvent( ES_GAME, SDLK_F1 );
82  subscribeEvent( ES_MENU, KeyMapper::PEV_FIRE1 );
83
84  this->input = new OrxGui::GLGuiInputLine();
85  this->input->setAbsCoor2D(180, 5);
86  this->input->enterPushed.connect(this, &MultiplayerTeamDeathmatch::onInputEnter);
87}
88
89/**
90 * decontsructor
91 */
92MultiplayerTeamDeathmatch::~MultiplayerTeamDeathmatch()
93{
94  unsubscribeEvent( ES_GAME, SDLK_o );
95  unsubscribeEvent( ES_GAME, SDLK_TAB );
96  unsubscribeEvent( ES_GAME, SDLK_F1 );
97  unsubscribeEvent( ES_MENU, KeyMapper::PEV_FIRE1 );
98
99  if ( this->input )
100  {
101    delete this->input;
102    this->input = NULL;
103  }
104}
105
106
107
108void MultiplayerTeamDeathmatch::loadParams(const TiXmlElement* root)
109{
110  GameRules::loadParams(root) ;
111
112  LoadParam(root, "death-penalty-timeout", this, MultiplayerTeamDeathmatch, setDeathPenaltyTimeout)
113  .describe("sets the time in seconds a player has to wait for respawn");
114
115  LoadParam(root, "max-kills", this, MultiplayerTeamDeathmatch, setMaxKills)
116  .describe("sets the maximal kills for winning condition");
117
118  LoadParam(root, "num-teams", this, MultiplayerTeamDeathmatch, setNumTeams)
119  .describe("sets number of teams");
120
121}
122
123
124/**
125 * time tick
126 * @param dt time
127 */
128void MultiplayerTeamDeathmatch::tick(float dt)
129{
130  tickStatsTable();
131  //on client side hostId is -1 until hanshake finished
132  if ( SharedNetworkData::getInstance()->getHostID() < 0 )
133    return;
134
135  if ( currentGameState == GAMESTATE_PRE_GAME || currentGameState == GAMESTATE_GAME )
136  {
137    if ( PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() ) &&
138         box == NULL &&
139         (PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPreferedTeamId() == TEAM_NOTEAM || bShowTeamChange )
140
141       )
142    {
143      EventHandler::getInstance()->pushState( ES_MENU );
144
145      OrxGui::GLGuiHandler::getInstance()->activateCursor();
146
147      box = new OrxGui::GLGuiBox();
148      box->setAbsCoor2D( 300, 100 );
149
150      OrxGui::GLGuiPushButton * buttonSpectator = new OrxGui::GLGuiPushButton("Spectator");
151      box->pack( buttonSpectator );
152      buttonSpectator->released.connect(this, &MultiplayerTeamDeathmatch::onButtonSpectator);
153
154      OrxGui::GLGuiPushButton * buttonRandom = new OrxGui::GLGuiPushButton("Random");
155      box->pack( buttonRandom );
156      buttonRandom->released.connect(this, &MultiplayerTeamDeathmatch::onButtonRandom);
157
158      OrxGui::GLGuiPushButton * buttonTeam0 = new OrxGui::GLGuiPushButton("Blue Team");
159      box->pack( buttonTeam0 );
160      buttonTeam0->released.connect(this, &MultiplayerTeamDeathmatch::onButtonTeam0);
161
162      OrxGui::GLGuiPushButton * buttonTeam1 = new OrxGui::GLGuiPushButton("Red Team");
163      box->pack( buttonTeam1 );
164      buttonTeam1->released.connect(this, &MultiplayerTeamDeathmatch::onButtonTeam1);
165
166      if ( bShowTeamChange )
167      {
168        OrxGui::GLGuiPushButton * buttonCancel = new OrxGui::GLGuiPushButton("Cancel");
169        box->pack( buttonCancel );
170        buttonCancel->released.connect(this, &MultiplayerTeamDeathmatch::onButtonCancel);
171      }
172
173      OrxGui::GLGuiPushButton * buttonExit = new OrxGui::GLGuiPushButton("Exit");
174      box->pack( buttonExit );
175      buttonExit->released.connect(this, &MultiplayerTeamDeathmatch::onButtonExit);
176
177      box->showAll();
178    }
179  }
180
181  //   if( PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() ) )
182  //   {
183  //     PRINTF(0)("prefered team id: %i, noteam: %i\n", PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPreferedTeamId(), TEAM_NOTEAM);
184  //   }
185
186  // check if the menu should be removed and the game state should be entered
187  if ( box != NULL &&
188       PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() ) &&
189       PlayerStats::getStats( SharedNetworkData::getInstance()->getHostID() )->getPreferedTeamId() != TEAM_NOTEAM &&
190       !bShowTeamChange
191     )
192  {
193    delete box;
194    box = NULL;
195
196    OrxGui::GLGuiHandler::getInstance()->deactivateCursor( true );
197
198    EventHandler::getInstance()->popState();
199  }
200
201  if ( box != NULL )
202  {
203    OrxGui::GLGuiHandler::getInstance()->tick( dt );
204  }
205
206  assignPlayable();
207
208  if ( SharedNetworkData::getInstance()->isClient() || SharedNetworkData::getInstance()->isProxyServerActive())
209    return;
210
211  //handle kills
212  while ( this->killList.begin() != this->killList.end() )
213  {
214    PRINTF(0)("KKKKKKKKIIIIIIIIILLLLLLLLLLLLL\n");
215    onKill( this->killList.begin()->getVictim(), this->killList.begin()->getKiller() );
216    this->killList.erase( this->killList.begin() );
217  }
218
219
220
221  gameStateTimer -= dt;
222  //PRINTF(0)("TICK %f\n", gameStateTimer);
223
224  if ( currentGameState != GAMESTATE_GAME && gameStateTimer < 0 )
225    nextGameState();
226
227  this->currentGameState = NetworkGameManager::getInstance()->getGameState();
228
229  if ( currentGameState == GAMESTATE_GAME )
230  {
231    handleTeamChanges();
232  }
233
234  this->calculateTeamScore();
235
236  this->checkGameRules();
237
238  // is the local player dead and inactive
239  if( unlikely(this->bLocalPlayerDead))
240  {
241    this->timeout += dt;
242    PRINTF(0)("TICK DEATH: %f of %f\n", this->timeout, this->deathTimeout);
243    // long enough dead?
244    if( this->timeout >= this->deathTimeout)
245    {
246      this->timeout = 0.0f;
247      // respawn
248      PRINTF(0)("RESPAWN\n");
249      (State::getPlayer())->getPlayable()->respawn();
250    }
251  }
252}
253
254
255/**
256 * draws the stuff
257 */
258void MultiplayerTeamDeathmatch::draw()
259{
260  if( unlikely( this->bLocalPlayerDead))
261  {
262  }
263}
264
265
266/**
267 * check the game rules for consistency
268 */
269void MultiplayerTeamDeathmatch::checkGameRules()
270{
271  if ( SharedNetworkData::getInstance()->isClient() || SharedNetworkData::getInstance()->isProxyServerActive())
272    return;
273
274  // check for max killing count
275  for ( int i = 0; i<numTeams; i++ )
276  {
277    if ( teamScore[i] >= maxKills )
278    {
279      nextGameState();
280    }
281  }
282}
283
284/**
285 * find group for new player
286 * @return group id
287 */
288int MultiplayerTeamDeathmatch::getTeamForNewUser()
289{
290  return TEAM_NOTEAM;
291}
292
293ClassID MultiplayerTeamDeathmatch::getPlayableClassId( int userId, int team )
294{
295  if ( team == TEAM_NOTEAM || team == TEAM_SPECTATOR )
296    return ObjectListBase::retrieveIdentity("Spectator");
297
298  if ( team == 0 || team == 1 )
299    return ObjectListBase::retrieveIdentity("FPSPlayer");
300
301  assert( false );
302}
303
304
305std::string MultiplayerTeamDeathmatch::getPlayableModelFileName( int userId, int team, const ClassID& classId )
306{
307  if (classId == CL_TURBINE_HOVER)
308  {
309    assert(false);
310    return "models/ships/hoverglider_mainbody.obj";
311  }
312  if ( team == 0 )
313    return "models/creatures/doom_guy.md2";
314  else if ( team == 1 )
315    return "models/creatures/male.md2";
316  else
317  {
318    return "";
319  }
320}
321
322std::string MultiplayerTeamDeathmatch::getPlayableModelTextureFileName( int userId, int team, const ClassID& classId )
323{
324  if ( team == 0 || team == 1 )
325  {
326    if ( team == 0 )
327      return "doom_guy.png";
328    else
329      return "male_fiend.pcx";
330  }
331
332  return "";
333}
334
335float MultiplayerTeamDeathmatch::getPlayableScale( int userId, int team, const ClassID& classId )
336{
337  if ( classId == ObjectListBase::retrieveIdentity(CL_FPS_PLAYER))
338  {
339    return 10.0f;
340  }
341
342  return 1.0f;
343}
344
345/**
346 * calculate team score
347 */
348void MultiplayerTeamDeathmatch::calculateTeamScore( )
349{
350  teamScore.clear();
351
352  for ( int i = 0; i<numTeams; i++ )
353    teamScore[i] = 0;
354
355  for (ObjectList<PlayerStats>::const_iterator it = PlayerStats::objectList().begin();
356       it != PlayerStats::objectList().end();
357       ++it)
358  {
359    PlayerStats & stats = *(*it);
360
361    if ( stats.getTeamId() >= 0 )
362    {
363      teamScore[stats.getTeamId()] += stats.getScore();
364    }
365  }
366}
367
368/**
369 * get team for player who choose to join random team
370 * @return smallest team
371 */
372int MultiplayerTeamDeathmatch::getRandomTeam( )
373{
374  std::map<int,int> playersInTeam;
375
376  for ( int i = 0; i<numTeams; i++ )
377    playersInTeam[i] = 0;
378
379  for (ObjectList<PlayerStats>::const_iterator it = PlayerStats::objectList().begin();
380       it != PlayerStats::objectList().end();
381       ++it)
382  {
383    PlayerStats & stats = *(*it);
384
385    if ( stats.getTeamId() >= 0 )
386    {
387      playersInTeam[stats.getTeamId()]++;
388    }
389  }
390
391
392  int minPlayers = 0xFFFF;
393  int minTeam = -1;
394
395  for ( int i = 0; i<numTeams; i++ )
396  {
397    if ( playersInTeam[i] < minPlayers )
398    {
399      minTeam = i;
400      minPlayers = playersInTeam[i];
401    }
402  }
403
404  assert( minTeam != -1 );
405
406  return minTeam;
407}
408
409void MultiplayerTeamDeathmatch::nextGameState( )
410{
411  if ( currentGameState == GAMESTATE_PRE_GAME )
412  {
413    NetworkGameManager::getInstance()->setGameState( GAMESTATE_GAME );
414
415    return;
416  }
417
418  if ( currentGameState == GAMESTATE_GAME )
419  {
420    NetworkGameManager::getInstance()->setGameState( GAMESTATE_POST_GAME );
421
422    return;
423  }
424
425  if ( currentGameState == GAMESTATE_POST_GAME )
426  {
427    //State::getCurrentStoryEntity()->stop();
428    this->bShowTeamChange = false;
429
430    return;
431  }
432}
433
434/**
435 *  this handles team changes but only on the master server
436 */
437void MultiplayerTeamDeathmatch::handleTeamChanges( )
438{
439  for (ObjectList<PlayerStats>::const_iterator it = PlayerStats::objectList().begin();
440       it != PlayerStats::objectList().end();
441       ++it)
442  {
443    PlayerStats & stats = *(*it);
444
445    if ( stats.getTeamId() != stats.getPreferedTeamId() )
446    {
447      if ( stats.getPreferedTeamId() == TEAM_SPECTATOR || ( stats.getPreferedTeamId() >= 0 && stats.getPreferedTeamId() < numTeams ) )
448      {
449        teamChange( stats.getAssignedUserId() );
450      }
451    }
452  }
453
454  //now serve player who want join a random team
455  for (ObjectList<PlayerStats>::const_iterator it = PlayerStats::objectList().begin();
456       it != PlayerStats::objectList().end();
457       ++it)
458  {
459    PlayerStats & stats = *(*it);
460
461    if ( stats.getTeamId() != stats.getPreferedTeamId() )
462    {
463      if ( stats.getPreferedTeamId() == TEAM_RANDOM )
464      {
465        stats.setPreferedTeamId( getRandomTeam() );
466        teamChange( stats.getAssignedUserId() );
467      }
468    }
469  }
470}
471
472
473
474/**
475 * changes the team
476 * @param userId the user changing team (userId)
477 */
478void MultiplayerTeamDeathmatch::teamChange( int userId )
479{
480  assert( PlayerStats::getStats( userId ) );
481  PlayerStats & stats = *(PlayerStats::getStats( userId ));
482
483  stats.setTeamId( stats.getPreferedTeamId() );
484
485  Playable * oldPlayable = stats.getPlayable();
486
487
488  ClassID       playableClassId  = getPlayableClassId( userId, stats.getPreferedTeamId() );
489  std::string   playableModel    = getPlayableModelFileName( userId, stats.getPreferedTeamId(), playableClassId );
490  std::string   playableTexture  = getPlayableModelTextureFileName( userId, stats.getPreferedTeamId(), playableClassId );
491  float         playableScale    = getPlayableScale( userId, stats.getPreferedTeamId(), playableClassId );
492
493  BaseObject * bo = Factory::fabricate( playableClassId );
494
495  assert( bo != NULL );
496  assert( bo->isA( Playable::staticClassID() ) );
497
498  Playable & playable = *(dynamic_cast<Playable*>(bo));
499
500  PRINTF(0)("%s %s %f\n", playableModel.c_str(), playableTexture.c_str(), playableScale );
501 
502  playable.loadMD2Texture( playableTexture );
503  playable.loadModel( playableModel, playableScale );
504  playable.setOwner( userId );
505  playable.setUniqueID( SharedNetworkData::getInstance()->getNewUniqueID() );
506  playable.setSynchronized( true );
507
508  stats.setPlayableClassId( playableClassId );
509  stats.setPlayableUniqueId( playable.getUniqueID() );
510  stats.setModelFileName( playableModel );
511  stats.setTeamId( stats.getPreferedTeamId() );
512
513  playable.setTeam(stats.getPreferedTeamId());
514
515
516  this->respawnPlayable( &playable, stats.getPreferedTeamId(), 0.0f );
517
518  if ( oldPlayable )
519  {
520    delete oldPlayable;
521  }
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/**
563 * function that processes events from the handler
564 * @param event: the event
565 * @todo replace SDLK_o with something from KeyMapper
566 */
567void MultiplayerTeamDeathmatch::process( const Event & event )
568{
569  if ( event.type == SDLK_o )
570  {
571    if ( event.bPressed )
572      this->bShowTeamChange = true;
573  }
574  else if ( event.type == SDLK_F1 )
575  {
576    if ( this->statsBox && !this->bLocalPlayerDead && event.bPressed )
577    {
578      PRINTF(5)("hide stats\n");
579      this->hideStats();
580    }
581    else if ( !this->statsBox && event.bPressed )
582    {
583      PRINTF(5)("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() == NULL || victimStats.getPlayable() == NULL)
746  {
747    PRINTF(0)("killerStats.getPlayable() != NULL || victimStats.getPlayable() != NULL\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
801/**
802 * respawns a playable in the world via spawning points
803 * @param playable the playable to respawn
804 * @param teamId the teamId to use
805 * @param delay time delay for delayed spawning
806 */
807void MultiplayerTeamDeathmatch::respawnPlayable( Playable * playable, int teamId, float delay )
808{
809
810  std::vector<SpawningPoint*> spList;
811
812  for (ObjectList<SpawningPoint>::const_iterator it = SpawningPoint::objectList().begin();
813       it != SpawningPoint::objectList().end();
814       ++it)
815  {
816    SpawningPoint * sp = (*it);
817
818    if ( sp->getTeamId() == teamId )
819      spList.push_back( sp );
820  }
821
822  if ( spList.size() == 0 )
823  {
824    for (ObjectList<SpawningPoint>::const_iterator it = SpawningPoint::objectList().begin();
825         it != SpawningPoint::objectList().end();
826         ++it)
827    {
828      SpawningPoint * sp = (*it);
829
830      if ( sp->getTeamId() < 0 )
831        spList.push_back( sp );
832    }
833  }
834
835  assert( spList.size() != 0 );
836
837  int n = (int)((float)spList.size() * (float)rand()/(float)RAND_MAX);
838
839  spList[n]->pushEntity( playable, delay );
840}
841
842
Note: See TracBrowser for help on using the repository browser.