src/game/game_loop.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *  Wormux is a convivial mass murder game.
00003  *  Copyright (C) 2001-2004 Lawrence Azzoug.
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00018  ******************************************************************************
00019  * Game loop : drawing and data handling
00020  *****************************************************************************/
00021 
00022 #include "game_loop.h"
00023 #include <SDL.h>
00024 #include <SDL_image.h>
00025 #include <sstream>
00026 #include <iostream>
00027 #include "config.h"
00028 #include "game.h"
00029 #include "game_mode.h"
00030 #include "time.h"
00031 #include "../ai/ai_engine.h"
00032 #include "../graphic/fps.h"
00033 #include "../graphic/video.h"
00034 #include "../include/action_handler.h"
00035 #include "../include/app.h"
00036 #include "../include/constant.h"
00037 #include "../interface/cursor.h"
00038 #include "../interface/game_msg.h"
00039 #include "../interface/interface.h"
00040 #include "../interface/keyboard.h"
00041 #include "../interface/loading_screen.h"
00042 #include "../interface/mouse.h"
00043 #include "../map/camera.h"
00044 #include "../map/map.h"
00045 #include "../map/maps_list.h"
00046 #include "../map/wind.h"
00047 #include "../network/network.h"
00048 #include "../network/randomsync.h"
00049 #include "../object/bonus_box.h"
00050 #include "../object/objects_list.h"
00051 #include "../particles/particle.h"
00052 #include "../sound/jukebox.h"
00053 #include "../team/macro.h"
00054 #include "../tool/debug.h"
00055 #include "../tool/i18n.h"
00056 #include "../tool/stats.h"
00057 #include "../weapon/weapons_list.h"
00058 
00059 
00060 #define ENABLE_LIMIT_FPS
00061 
00062 bool game_fin_partie;
00063 
00064 GameLoop * GameLoop::singleton = NULL;
00065 
00066 GameLoop * GameLoop::GetInstance()
00067 {
00068   if (singleton == NULL) {
00069     singleton = new GameLoop();
00070   }
00071   return singleton;
00072 }
00073 
00074 GameLoop::GameLoop()
00075 {
00076   state = PLAYING;
00077   interaction_enabled = true;
00078 }
00079 
00080 void GameLoop::InitGameData_NetServer()
00081 {
00082   network.client_inited = 1;
00083   AppWormux * app = AppWormux::GetInstance();
00084   app->video.SetWindowCaption( std::string("Wormux ") + Constants::VERSION + " - Server mode");
00085 
00086   ActionHandler * action_handler = ActionHandler::GetInstance();
00087 
00088   network.RejectIncoming();
00089 
00090   Action a_change_state(Action::ACTION_CHANGE_STATE);
00091   network.SendAction ( &a_change_state );
00092   network.state = Network::NETWORK_INIT_GAME;
00093 
00094   SendGameMode();
00095 
00096   world.Reset();
00097 
00098   randomSync.Init();
00099 
00100   lst_objects.PlaceBarrels();
00101 
00102   std::cout << "o " << _("Initialise teams") << std::endl;
00103   teams_list.LoadGamingData(GameMode::GetInstance()->max_characters);
00104 
00105   lst_objects.PlaceMines();
00106   std::cout << "o " << _("Initialise data") << std::endl;
00107   CharacterCursor::GetInstance()->Reset();
00108   Mouse::GetInstance()->Reset();
00109   fps.Reset();
00110   Interface::GetInstance()->Reset();
00111   GameMessages::GetInstance()->Reset();
00112 
00113   // Tells all clients that the server is ready to play
00114   network.SendAction ( &a_change_state );
00115 
00116   // Wait for all clients to be ready to play
00117   while (network.state != Network::NETWORK_READY_TO_PLAY)
00118   {
00119     action_handler->ExecActions();
00120     SDL_Delay(200);
00121   }
00122   network.SendAction ( &a_change_state );
00123   network.state = Network::NETWORK_PLAYING;
00124 }
00125 
00126 void GameLoop::InitGameData_NetClient()
00127 {
00128   AppWormux * app = AppWormux::GetInstance();
00129   app->video.SetWindowCaption( std::string("Wormux ") + Constants::VERSION + " - Client mode");
00130   ActionHandler * action_handler = ActionHandler::GetInstance();
00131   std::cout << "o " << _("Initialise teams") << std::endl;
00132 
00133   world.Reset();
00134 
00135   lst_objects.PlaceBarrels();
00136   teams_list.LoadGamingData(GameMode::GetInstance()->max_characters);
00137   lst_objects.PlaceMines();
00138 
00139   Action a_change_state(Action::ACTION_CHANGE_STATE);
00140 
00141   network.SendAction (&a_change_state);
00142   while (network.state != Network::NETWORK_READY_TO_PLAY)
00143   {
00144     // The server is placing characters on the map
00145     // We can receive new team / map selection
00146     action_handler->ExecActions();
00147     SDL_Delay(100);
00148   }
00149 
00150   std::cout << network.state << " : Waiting for people over the network" << std::endl;
00151   while (network.state != Network::NETWORK_PLAYING)
00152   {
00153     // The server waits for everybody to be ready to start
00154     action_handler->ExecActions();
00155     SDL_Delay(100);
00156   }
00157   std::cout << network.state << " : Run game !" << std::endl;
00158 }
00159 
00160 void GameLoop::InitData_Local()
00161 {
00162   std::cout << "o " << _("Find a random position for characters") << std::endl;
00163   world.Reset();
00164   MapsList::GetInstance()->ActiveMap().FreeData();
00165   lst_objects.PlaceBarrels();
00166   teams_list.LoadGamingData(0);
00167 
00168   std::cout << "o " << _("Initialise objects") << std::endl;
00169   lst_objects.PlaceMines();
00170 }
00171 
00172 void GameLoop::InitData()
00173 {
00174   Time::GetInstance()->Reset();
00175 
00176   if (network.IsServer())
00177     InitGameData_NetServer();
00178   else if (network.IsClient())
00179     InitGameData_NetClient();
00180   else
00181     InitData_Local();
00182 
00183   CharacterCursor::GetInstance()->Reset();
00184   Mouse::GetInstance()->Reset();
00185   Config::GetInstance()->GetKeyboard()->Reset();
00186 
00187   fps.Reset();
00188   if(network.IsConnected())
00189      chatsession.Reset();
00190   Interface::GetInstance()->Reset();
00191   GameMessages::GetInstance()->Reset();
00192   ParticleEngine::Init();
00193 }
00194 
00195 void GameLoop::Init ()
00196 {
00197   // Display Loading screen
00198   LoadingScreen::GetInstance()->DrawBackground();
00199 
00200   Game::GetInstance()->MessageLoading();
00201 
00202   // Init all needed data
00203   std::cout << "o " << _("Initialisation") << std::endl;
00204 
00205   // Load the map
00206   LoadingScreen::GetInstance()->StartLoading(1, "map_icon", _("Maps"));
00207   InitData();
00208 
00209   // Init teams
00210   LoadingScreen::GetInstance()->StartLoading(2, "team_icon", _("Teams"));
00211 
00212   // Teams' creation
00213   if (teams_list.playing_list.size() < 2)
00214     Error(_("You need at least two teams to play: "
00215              "change this in 'Options menu' !"));
00216   assert (teams_list.playing_list.size() <= GameMode::GetInstance()->max_teams);
00217 
00218   // Initialization of teams' energy
00219   LoadingScreen::GetInstance()->StartLoading(3, "weapon_icon", _("Weapons"));
00220 
00221   teams_list.InitEnergy();
00222 
00223   // Load teams' sound profiles
00224   LoadingScreen::GetInstance()->StartLoading(4, "sound_icon", _("Sounds"));
00225 
00226   jukebox.LoadXML("default");
00227   FOR_EACH_TEAM(team)
00228     if ( (**team).GetSoundProfile() != "default" )
00229       jukebox.LoadXML((**team).GetSoundProfile()) ;
00230 
00231   // Begin to play !!
00232   // Music -> sound should be choosed in map.Init and then we just have to call jukebox.PlayMusic()
00233   if (jukebox.UseMusic()) jukebox.Play ("share", "music/grenouilles", -1);
00234 
00235   Game::GetInstance()->SetEndOfGameStatus( false );
00236 
00237   Mouse::GetInstance()->SetPointer(Mouse::POINTER_SELECT);
00238 
00239   // First "selection" of a weapon -> fix bug 6576
00240   ActiveTeam().AccessWeapon().Select();
00241 
00242   SetState(PLAYING, true);
00243 }
00244 
00245 void GameLoop::RefreshInput()
00246 {
00247   // Poll and treat keyboard and mouse events
00248   SDL_Event event;
00249 
00250   while(SDL_PollEvent(&event)) {
00251     if ( event.type == SDL_QUIT) {
00252       std::cout << "SDL_QUIT received ===> exit TODO" << std::endl;
00253       Game::GetInstance()->SetEndOfGameStatus( true );
00254       std::cout << "FIN PARTIE" << std::endl;
00255       return;
00256     }
00257     if ( event.type == SDL_MOUSEBUTTONDOWN ) {
00258       Mouse::GetInstance()->TraiteClic( &event);
00259     }
00260     if ( event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) {
00261       if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE) {
00262         Game::GetInstance()->SetEndOfGameStatus( true );
00263         std::cout << "FIN PARTIE" << std::endl;
00264         return;
00265       }
00266       Config::GetInstance()->GetKeyboard()->HandleKeyEvent( &event);
00267     }
00268   }
00269 
00270   if (!Time::GetInstance()->IsGamePaused()) {
00271     // Keyboard and mouse refresh
00272     if ((interaction_enabled && state != END_TURN) ||
00273         (ActiveTeam().GetWeapon().IsActive() &&
00274          ActiveTeam().GetWeapon().override_keys)) { // for driving supertux for example
00275       Mouse::GetInstance()->Refresh();
00276       Config::GetInstance()->GetKeyboard()->Refresh();
00277       AIengine::GetInstance()->Refresh();
00278     }
00279     // Execute action
00280     do {
00281       ActionHandler::GetInstance()->ExecActions();
00282       if(network.sync_lock) SDL_Delay(SDL_TIMESLICE);
00283     } while(network.sync_lock);
00284   }
00285   GameMessages::GetInstance()->Refresh();
00286   camera.Refresh();
00287 }
00288 
00289 void GameLoop::RefreshObject()
00290 {
00291   if (!Time::GetInstance()->IsGamePaused()) {
00292     FOR_ALL_CHARACTERS(team,character)
00293         character->Refresh();
00294     // Recompute energy of each team
00295     FOR_EACH_TEAM(team)
00296         (**team).Refresh();
00297     teams_list.RefreshEnergy();
00298 
00299     ActiveTeam().AccessWeapon().Manage();
00300     lst_objects.Refresh();
00301     ParticleEngine::Refresh();
00302     CharacterCursor::GetInstance()->Refresh();
00303   }
00304 }
00305 
00306 void GameLoop::Draw ()
00307 {
00308   // Draw the sky
00309   StatStart("GameDraw:sky");
00310   world.DrawSky();
00311   StatStop("GameDraw:sky");
00312 
00313   // Draw the map
00314   StatStart("GameDraw:world");
00315   world.Draw();
00316   StatStop("GameDraw:world");
00317 
00318   // Draw the characters
00319   StatStart("GameDraw:characters");
00320   FOR_ALL_CHARACTERS(team,character)
00321     if (!character->IsActiveCharacter())
00322       character->Draw();
00323 
00324   StatStart("GameDraw:particles_behind_active_character");
00325   ParticleEngine::Draw(false);
00326   StatStop("GameDraw:particles_behind_active_character");
00327 
00328   StatStart("GameDraw:active_character");
00329   ActiveCharacter().Draw();
00330   if (!ActiveCharacter().IsDead() && state != END_TURN) {
00331         ActiveTeam().crosshair.Draw();
00332         ActiveTeam().AccessWeapon().Draw();
00333   }
00334   StatStop("GameDraw:active_character");
00335   StatStop("GameDraw:characters");
00336 
00337   // Draw objects
00338   StatStart("GameDraw:objects");
00339   lst_objects.Draw();
00340   ParticleEngine::Draw(true);
00341   StatStart("GameDraw:objects");
00342 
00343   // Draw arrow on top of character
00344   StatStart("GameDraw:arrow_character");
00345   CharacterCursor::GetInstance()->Draw();
00346   StatStop("GameDraw:arrow_character");
00347 
00348   // Draw waters
00349   StatStart("GameDraw:water");
00350   world.DrawWater();
00351   StatStop("GameDraw:water");
00352 
00353   // Draw game messages
00354   StatStart("GameDraw::game_messages");
00355   GameMessages::GetInstance()->Draw();
00356   StatStop("GameDraw::game_messages");
00357 
00358   // Draw optionals
00359   StatStart("GameDraw:fps_and_map_author_name");
00360   world.DrawAuthorName();
00361   fps.Draw();
00362   StatStop("GameDraw:fps_and_map_author_name");
00363 
00364   StatStop("GameDraw:other");
00365 
00366   // Draw the interface (current team's information, weapon's ammo)
00367   StatStart("GameDraw:interface");
00368   Interface::GetInstance()->Draw ();
00369   StatStop("GameDraw:interface");
00370 
00371   // Draw MsgBox for chat network
00372   if(network.IsConnected()){
00373     StatStart("GameDraw:chatsession");
00374     chatsession.Show();
00375     StatStop("GameDraw:chatsession");
00376   }
00377 
00378   // Add one frame to the fps counter ;-)
00379   fps.AddOneFrame();
00380 
00381   // Draw the mouse pointer
00382   StatStart("GameDraw:mouse_pointer");
00383   Mouse::GetInstance()->Draw();
00384   StatStart("GameDraw:mouse_pointer");
00385 }
00386 
00387 void GameLoop::CallDraw()
00388 {
00389   Draw();
00390   StatStart("GameDraw:flip()");
00391   AppWormux::GetInstance()->video.Flip();
00392   StatStop("GameDraw:flip()");
00393 }
00394 
00395 void GameLoop::PingClient()
00396 {
00397   Action * a = new Action(Action::ACTION_PING);
00398   ActionHandler::GetInstance()->NewAction(a);
00399 }
00400 
00401 void GameLoop::Run()
00402 {
00403   int delay = 0;
00404   uint time_of_next_frame = SDL_GetTicks();
00405   uint previous_time_frame = 0;
00406 
00407   // loop until game is finished
00408   do
00409   {
00410     Game::GetInstance()->SetEndOfGameStatus( false );
00411 
00412     // Refresh clock value
00413     RefreshClock();
00414     if(Time::GetInstance()->Read() % 1000 == 20 && network.IsServer())
00415       PingClient();
00416     StatStart("GameLoop:RefreshInput()");
00417     RefreshInput();
00418     StatStop("GameLoop:RefreshInput()");
00419     if(previous_time_frame < Time::GetInstance()->Read()) {
00420       StatStart("GameLoop:RefreshObject()");
00421       RefreshObject();
00422       StatStop("GameLoop:RefreshObject()");
00423     } else {
00424       previous_time_frame = Time::GetInstance()->Read();
00425     }
00426     // Refresh the map
00427     world.Refresh();
00428     // try to adjust to max Frame by seconds
00429     time_of_next_frame += Time::GetInstance()->GetDelta();
00430     if (time_of_next_frame > SDL_GetTicks()) {
00431       StatStart("GameLoop:Draw()");
00432       CallDraw();
00433       // How many frame by seconds ?
00434       fps.Refresh();
00435       StatStop("GameLoop:Draw()");
00436     }
00437     delay = time_of_next_frame - SDL_GetTicks();
00438     if (delay >= 0)
00439       SDL_Delay(delay);
00440   } while( !Game::GetInstance()->GetEndOfGameStatus() );
00441 }
00442 
00443 void GameLoop::RefreshClock()
00444 {
00445   Time * global_time = Time::GetInstance();
00446   if (global_time->IsGamePaused()) return;
00447   global_time->Refresh();
00448 
00449   if (1000 < global_time->Read() - pause_seconde)
00450     {
00451       pause_seconde = global_time->Read();
00452 
00453       switch (state) {
00454 
00455       case PLAYING:
00456         if (duration <= 1) {
00457            jukebox.Play("share", "end_turn");
00458            SetState(END_TURN);
00459         } else {
00460           duration--;
00461           Interface::GetInstance()->UpdateTimer(duration);
00462         }
00463         break;
00464 
00465       case HAS_PLAYED:
00466         if (duration <= 1) {
00467           SetState (END_TURN);
00468         } else {
00469           duration--;
00470           Interface::GetInstance()->UpdateTimer(duration);
00471         }
00472         break;
00473 
00474       case END_TURN:
00475         if (duration <= 1) {
00476 
00477           if (IsAnythingMoving()) {
00478             duration = 1;
00479             // Hack to be sure that nothing is moving since enough time
00480             // it avoids giving hand to another team during the end of an explosion for example
00481             break;
00482           }
00483 
00484           if (Game::GetInstance()->IsGameFinished())
00485             Game::GetInstance()->SetEndOfGameStatus( true );
00486           else if (BonusBox::NewBonusBox())
00487             break;
00488           else {
00489             ActiveTeam().AccessWeapon().Deselect();
00490             SetState(PLAYING);
00491             break;
00492           }
00493         } else {
00494           duration--;
00495         }
00496         break;
00497       } // switch
00498     }// if
00499 }
00500 
00501 void GameLoop::SetState(int new_state, bool begin_game)
00502 {
00503   ActionHandler * action_handler = ActionHandler::GetInstance();
00504 
00505   // already in good state, nothing to do
00506   if ((state == new_state) && !begin_game) return;
00507 
00508   state = new_state;
00509 
00510   if(begin_game)
00511     action_handler->ExecActions();
00512 
00513   Interface::GetInstance()->weapons_menu.Hide();
00514 
00515   Time * global_time = Time::GetInstance();
00516   GameMode * game_mode = GameMode::GetInstance();
00517 
00518   switch (state)
00519   {
00520   // Begining of a new turn:
00521   case PLAYING:
00522     MSG_DEBUG("game.statechange", "Playing" );
00523     // Center the cursor
00524     Mouse::GetInstance()->CenterPointer();
00525 
00526     // Init. le compteur
00527     duration = game_mode->duration_turn;
00528     Interface::GetInstance()->UpdateTimer(duration);
00529     Interface::GetInstance()->EnableDisplayTimer(true);
00530     pause_seconde = global_time->Read();
00531 
00532     if (network.IsServer() || network.IsLocal())
00533      wind.ChooseRandomVal();
00534 
00535      character_already_chosen = false;
00536 
00537     // Prepare each character for a new turn
00538     FOR_ALL_LIVING_CHARACTERS(team,character)
00539         character->PrepareTurn();
00540 
00541     // Select the next team
00542     assert (!Game::GetInstance()->IsGameFinished());
00543 
00544     if(network.IsLocal() || network.IsServer())
00545     {
00546       do
00547       {
00548         teams_list.NextTeam (begin_game);
00549         action_handler->ExecActions();
00550       } while (ActiveTeam().NbAliveCharacter() == 0);
00551 
00552 
00553       if( game_mode->allow_character_selection==GameMode::CHANGE_ON_END_TURN
00554        || game_mode->allow_character_selection==GameMode::BEFORE_FIRST_ACTION_AND_END_TURN)
00555       {
00556         ActiveTeam().NextCharacter();
00557       }
00558 
00559       if( network.IsServer() )
00560       {
00561         // Tell to clients which character in the team is now playing
00562         Action playing_char(Action::ACTION_CHANGE_CHARACTER);
00563         playing_char.StoreActiveCharacter();
00564         network.SendAction(&playing_char);
00565 
00566         printf("Action_ChangeCharacter:\n");
00567         printf("char_index = %i\n",ActiveCharacter().GetCharacterIndex());
00568         printf("Playing character : %i %s\n", ActiveCharacter().GetCharacterIndex(), ActiveCharacter().GetName().c_str());
00569         printf("Playing team : %i %s\n", ActiveCharacter().GetTeamIndex(), ActiveTeam().GetName().c_str());
00570         printf("Alive characters: %i / %i\n\n",ActiveTeam().NbAliveCharacter(),ActiveTeam().GetNbCharacters());
00571 
00572       }
00573     }
00574 
00575     action_handler->ExecActions();
00576 
00577 //    assert (!ActiveCharacter().IsDead());
00578     camera.FollowObject (&ActiveCharacter(), true, true);
00579     interaction_enabled = true; // Be sure that we can play !
00580 
00581     // Applying Disease damage and Death mode.
00582     ApplyDiseaseDamage();
00583     ApplyDeathMode();
00584 
00585     break;
00586 
00587   // The character have shooted, but can still move
00588   case HAS_PLAYED:
00589     MSG_DEBUG("game.statechange", "Has played, now can move");
00590     duration = game_mode->duration_move_player;
00591     pause_seconde = global_time->Read();
00592     Interface::GetInstance()->UpdateTimer(duration);
00593     CharacterCursor::GetInstance()->Hide();
00594     break;
00595 
00596   // Little pause at the end of the turn
00597   case END_TURN:
00598     MSG_DEBUG("game.statechange", "End of turn");
00599     ActiveTeam().AccessWeapon().SignalTurnEnd();
00600     CharacterCursor::GetInstance()->Hide();
00601     duration = game_mode->duration_exchange_player;
00602     Interface::GetInstance()->UpdateTimer(duration);
00603     Interface::GetInstance()->EnableDisplayTimer(false);
00604     pause_seconde = global_time->Read();
00605 
00606     interaction_enabled = false; // Be sure that we can NOT play !
00607     if(network.IsServer())
00608       SyncCharacters(); // Send information about energy and the position of every character
00609     break;
00610   }
00611 }
00612 
00613 PhysicalObj* GameLoop::GetMovingObject()
00614 {
00615   if (!ActiveCharacter().IsImmobile()) return &ActiveCharacter();
00616 
00617   FOR_ALL_CHARACTERS(team,character)
00618   {
00619     if (!character->IsImmobile() && !character->IsGhost())
00620     {
00621       MSG_DEBUG("game.endofturn", "%s is not ready", character->GetName().c_str())
00622       return &(*character);
00623     }
00624   }
00625 
00626   FOR_EACH_OBJECT(object)
00627   {
00628     if (!(*object)->IsImmobile())
00629     {
00630       MSG_DEBUG("game.endofturn", "%s is moving", (*object)->GetName().c_str())
00631       return (*object);
00632     }
00633   }
00634 
00635   return ParticleEngine::IsSomethingMoving();
00636 }
00637 
00638 bool GameLoop::IsAnythingMoving()
00639 {
00640   // Is the weapon still active or an object still moving ??
00641   bool object_still_moving = false;
00642 
00643   if (ActiveTeam().GetWeapon().IsActive()) object_still_moving = true;
00644 
00645   if (!object_still_moving)
00646   {
00647     PhysicalObj *obj = GetMovingObject();
00648     if (obj != NULL)
00649     {
00650       camera.FollowObject (obj, true, true);
00651       object_still_moving = true;
00652     }
00653   }
00654 
00655   return object_still_moving;
00656 }
00657 
00658 // Signal death of a character
00659 void GameLoop::SignalCharacterDeath (Character *character)
00660 {
00661   std::string txt;
00662 
00663   if (!Game::GetInstance()->IsGameLaunched())
00664     return;
00665 
00666   if (character -> IsDrowned()) {
00667     txt = Format(_("%s has fallen in water."), character -> GetName().c_str());
00668 
00669   } else if (&ActiveCharacter() == character) { // Active Character is dead
00670     CharacterCursor::GetInstance()->Hide();
00671 
00672     // Is this a suicide ?
00673     if (ActiveTeam().GetWeaponType() == Weapon::WEAPON_SUICIDE) {
00674       txt = Format(_("%s commits suicide !"), character -> GetName().c_str());
00675 
00676       // Dead in moving ?
00677     } else if (state == PLAYING) {
00678       txt = Format(_("%s has fallen off the map!"),
00679                    character -> GetName().c_str());
00680        jukebox.Play(ActiveTeam().GetSoundProfile(), "out");
00681 
00682       // The playing character killed hisself
00683     } else {
00684       txt = Format(_("%s is dead because he is clumsy!"),
00685                    character -> GetName().c_str());
00686     }
00687   } else if (!ActiveCharacter().IsDead()
00688              && character->GetTeam().IsSameAs(ActiveTeam()) ) {
00689     txt = Format(_("%s is a psychopath, he has killed a member of %s team!"),
00690                  ActiveCharacter().GetName().c_str(), character -> GetName().c_str());
00691   } else if (ActiveTeam().GetWeaponType() == Weapon::WEAPON_GUN) {
00692     txt = Format(_("What a shame for %s - he was killed by a simple gun!"),
00693                  character -> GetName().c_str());
00694   } else {
00695     txt = Format(_("%s (%s) has died."),
00696                  character -> GetName().c_str(),
00697                  character -> GetTeam().GetName().c_str());
00698   }
00699 
00700   GameMessages::GetInstance()->Add (txt);
00701 
00702   // Turn end if the playing character is dead
00703   if (character->IsActiveCharacter())
00704     SetState(END_TURN);
00705 }
00706 
00707 // Signal falling or any kind of damage of a character
00708 void GameLoop::SignalCharacterDamage(Character *character)
00709 {
00710   if (character->IsActiveCharacter())
00711     SetState(END_TURN);
00712 }
00713 
00714 // Apply Disease damage
00715 void GameLoop::ApplyDiseaseDamage()
00716 {
00717   FOR_ALL_LIVING_CHARACTERS(team, character) {
00718     if (character->IsDiseased()) {
00719       character->SetEnergyDelta(-character->GetDiseaseDamage());
00720       character->DecDiseaseDuration();
00721     }
00722   }
00723 }
00724 
00725 // Reduce energy of each character if we are in death mode
00726 void GameLoop::ApplyDeathMode ()
00727 {
00728   if(Time::GetInstance()->Read() > GameMode::GetInstance()->duration_before_death_mode * 1000)
00729   {
00730     GameMessages::GetInstance()->Add (_("Hurry up, you are too slow !!"));
00731     FOR_ALL_LIVING_CHARACTERS(team, character)
00732     {
00733       // If the character energy is lower than damage
00734       // per turn we reduce the character's health to 1
00735       if (static_cast<uint>(character->GetEnergy()) >
00736           GameMode::GetInstance()->damage_per_turn_during_death_mode)
00737         character->SetEnergyDelta(-GameMode::GetInstance()->damage_per_turn_during_death_mode);
00738       else
00739         character->SetEnergy(1);
00740     }
00741   }
00742 }

Generated on Mon Jan 1 13:10:56 2007 for Wormux by  doxygen 1.4.7