src/include/action_handler.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  * Wormux action handler.
00020  *****************************************************************************/
00021 
00022 #include "action_handler.h"
00023 #include "action.h"
00024 #include "../character/body.h"
00025 #include "../character/move.h"
00026 #include "../game/game_mode.h"
00027 #include "../game/game_loop.h"
00028 #include "../game/game.h"
00029 #include "../game/time.h"
00030 #include "../include/constant.h"
00031 #include "../network/network.h"
00032 #include "../map/camera.h"
00033 #include "../map/map.h"
00034 #include "../map/maps_list.h"
00035 #include "../map/wind.h"
00036 #include "../menu/network_menu.h"
00037 #include "../network/randomsync.h"
00038 #include "../network/network.h"
00039 #include "../team/macro.h"
00040 #include "../tool/debug.h"
00041 #include "../tool/i18n.h"
00042 #include "../tool/vector2.h"
00043 #include "../weapon/construct.h"
00044 #include "../weapon/launcher.h"
00045 #include "../weapon/supertux.h"
00046 #include "../weapon/weapon.h"
00047 #include "../weapon/weapons_list.h"
00048 #include "../weapon/explosion.h"
00049 
00050 // Delta angle used to move the crosshair
00051 #define DELTA_CROSSHAIR 0.035 /* ~1 degree */
00052 
00053 ActionHandler * ActionHandler::singleton = NULL;
00054 
00055 ActionHandler * ActionHandler::GetInstance()
00056 {
00057   if (singleton == NULL)
00058     singleton = new ActionHandler();
00059   return singleton;
00060 }
00061 
00062 // Send information about energy and the position of every character
00063 void SyncCharacters()
00064 {
00065   assert(network.IsServer());
00066   ActionHandler* action_handler = ActionHandler::GetInstance();
00067 
00068   Action a_begin_sync(Action::ACTION_SYNC_BEGIN);
00069   network.SendAction(&a_begin_sync);
00070   TeamsList::iterator
00071     it=teams_list.playing_list.begin(),
00072     end=teams_list.playing_list.end();
00073 
00074   for (int team_no = 0; it != end; ++it, ++team_no)
00075   {
00076     Team& team = **it;
00077     Team::iterator
00078         tit = team.begin(),
00079         tend = team.end();
00080 
00081     for (int char_no = 0; tit != tend; ++tit, ++char_no)
00082     {
00083       // Sync the character's energy
00084       Action* a = new Action(Action::ACTION_SET_CHARACTER_ENERGY);
00085       a->Push(team_no);
00086       a->Push(char_no);
00087       a->Push((int)(*tit).GetEnergy());
00088       action_handler->NewAction(a);
00089       // Sync the character's position
00090       a = BuildActionSendCharacterPhysics(team_no, char_no);
00091       action_handler->NewAction(a);
00092     }
00093   }
00094   Action a_sync_end(Action::ACTION_SYNC_END);
00095   network.SendAction(&a_sync_end);
00096 }
00097 
00098 void Action_MoveRight (Action *a)
00099 {
00100   assert(false);
00101   MoveCharacterRight (ActiveCharacter());
00102 }
00103 
00104 void Action_MoveLeft (Action *a)
00105 {
00106   assert(false);
00107   MoveCharacterLeft (ActiveCharacter());
00108 }
00109 
00110 void Action_Jump (Action *a)
00111 {
00112   GameLoop::GetInstance()->character_already_chosen = true;
00113   ActiveCharacter().Jump();
00114 }
00115 
00116 void Action_HighJump (Action *a)
00117 {
00118   GameLoop::GetInstance()->character_already_chosen = true;
00119   ActiveCharacter().HighJump();
00120 }
00121 
00122 void Action_BackJump (Action *a)
00123 {
00124   GameLoop::GetInstance()->character_already_chosen = true;
00125   ActiveCharacter().BackJump();
00126 }
00127 
00128 void Action_Up (Action *a)
00129 {
00130   ActiveCharacter().AddFiringAngle(-DELTA_CROSSHAIR);
00131 }
00132 
00133 void Action_Down (Action *a)
00134 {
00135   ActiveCharacter().AddFiringAngle(DELTA_CROSSHAIR);
00136 }
00137 
00138 void Action_ChangeWeapon (Action *a)
00139 {
00140   ActiveTeam().SetWeapon(static_cast<Weapon::Weapon_type>(a->PopInt()));
00141 }
00142 
00143 void Action_NextCharacter (Action *a)
00144 {
00145   a->RetrieveCharacter();       // Retrieve current character's informations
00146   a->RetrieveCharacter();       // Retrieve next character information
00147   camera.FollowObject(&ActiveCharacter(), true, true);
00148 }
00149 
00150 void Action_ChangeCharacter (Action *a)
00151 {
00152   a->RetrieveCharacter();
00153   camera.FollowObject(&ActiveCharacter(), true, true);
00154 }
00155 
00156 void Action_Shoot (Action *a)
00157 {
00158   double strength = a->PopDouble();
00159   double angle = a->PopDouble();
00160   a->RetrieveCharacter();
00161   ActiveTeam().AccessWeapon().PrepareShoot(strength, angle);
00162 }
00163 
00164 void Action_Wind (Action *a)
00165 {
00166   wind.SetVal (a->PopInt());
00167 }
00168 
00169 Action* BuildActionSendCharacterPhysics(int team_no, int char_no)
00170 {
00171   Action* a = new Action(Action::ACTION_SET_CHARACTER_PHYSICS);
00172   a->StoreCharacter(team_no, char_no);
00173   return a;
00174 }
00175 
00176 void Action_SetCharacterPhysics (Action *a)
00177 {
00178   while(!a->IsEmpty())
00179     a->RetrieveCharacter();
00180 }
00181 
00182 void Action_SetCharacterEnergy(Action *a)
00183 {
00184   int team_no, char_no;
00185   team_no = a->PopInt();
00186   char_no = a->PopInt();
00187   Character* c = teams_list.FindPlayingByIndex(team_no)->FindByIndex(char_no);
00188   c->SetEnergy( a->PopInt() );
00189 }
00190 
00191 void Action_SetSkin (Action *a)
00192 {
00193   //Set the frame of the walking skin, to get the position of the hand synced
00194   if (!ActiveTeam().IsLocal() || network.state != Network::NETWORK_PLAYING)
00195   {
00196     ActiveTeam().ActiveCharacter().SetClothe(a->PopString());
00197     ActiveTeam().ActiveCharacter().SetMovement(a->PopString());
00198     ActiveTeam().ActiveCharacter().body->SetFrame((uint)a->PopInt());
00199   }
00200 }
00201 
00202 void Action_SetCharacterDirection (Action *a)
00203 {
00204   ActiveCharacter().SetDirection (Body::Direction_t(a->PopInt()));
00205 }
00206 
00207 void Action_SetMap (Action *a)
00208 {
00209   if (!network.IsClient()) return;
00210   MapsList::GetInstance()->SelectMapByName(a->PopString());
00211   network.network_menu->ChangeMapCallback();
00212 }
00213 
00214 void Action_ChangeState (Action *a)
00215 {
00216   MSG_DEBUG("action.handler", "ChangeState");
00217 
00218   if(network.IsServer())
00219   {
00220     switch(network.state)
00221     {
00222     case Network::NETWORK_OPTION_SCREEN:
00223       // State is changed when server clicks on the launch game button
00224       network.client_inited++;
00225       break;
00226     case Network::NETWORK_INIT_GAME:
00227       // One more client is ready to play
00228       network.client_inited++;
00229       if(network.client_inited == network.connected_player)
00230         network.state = Network::NETWORK_READY_TO_PLAY;
00231       break;
00232     default:
00233       assert(false);
00234       break;
00235     }
00236   }
00237 
00238   if(network.IsClient())
00239   {
00240     switch(network.state)
00241     {
00242     case Network::NETWORK_OPTION_SCREEN:
00243       network.state = Network::NETWORK_INIT_GAME;
00244       break;
00245     case Network::NETWORK_INIT_GAME:
00246       network.state = Network::NETWORK_READY_TO_PLAY;
00247       break;
00248     case Network::NETWORK_READY_TO_PLAY:
00249       network.state = Network::NETWORK_PLAYING;
00250       break;
00251     default:
00252        assert(false);
00253     }
00254   }
00255 }
00256 
00257 void Action_SetGameMode (Action *a)
00258 {
00259   assert(network.IsClient());
00260   GameMode::GetInstance()->max_characters = a->PopInt();
00261   GameMode::GetInstance()->max_teams = a->PopInt();
00262   GameMode::GetInstance()->duration_turn = a->PopInt();
00263   GameMode::GetInstance()->duration_exchange_player = a->PopInt();
00264   GameMode::GetInstance()->duration_before_death_mode = a->PopInt();
00265   GameMode::GetInstance()->gravity = a->PopDouble();
00266   GameMode::GetInstance()->safe_fall = a->PopDouble();
00267   GameMode::GetInstance()->damage_per_fall_unit = a->PopDouble();
00268   GameMode::GetInstance()->duration_move_player = a->PopInt();
00269   GameMode::GetInstance()->allow_character_selection = a->PopInt();
00270   GameMode::GetInstance()->character.init_energy = a->PopInt();
00271   GameMode::GetInstance()->character.max_energy = a->PopInt();
00272   GameMode::GetInstance()->character.mass = a->PopInt();
00273   GameMode::GetInstance()->character.air_resist_factor = a->PopDouble();
00274   GameMode::GetInstance()->character.jump_strength = a->PopInt();
00275   GameMode::GetInstance()->character.jump_angle = a->PopDouble();
00276   GameMode::GetInstance()->character.super_jump_strength = a->PopInt();
00277   GameMode::GetInstance()->character.super_jump_angle = a->PopDouble();
00278   GameMode::GetInstance()->character.back_jump_strength = a->PopInt();
00279   GameMode::GetInstance()->character.back_jump_angle = a->PopDouble();
00280 }
00281 
00282 void SendGameMode()
00283 {
00284   assert(network.IsServer());
00285   Action a(Action::ACTION_SET_GAME_MODE);
00286   a.Push((int)GameMode::GetInstance()->max_characters);
00287   a.Push((int)GameMode::GetInstance()->max_teams);
00288   a.Push((int)GameMode::GetInstance()->duration_turn);
00289   a.Push((int)GameMode::GetInstance()->duration_exchange_player);
00290   a.Push((int)GameMode::GetInstance()->duration_before_death_mode);
00291   a.Push(GameMode::GetInstance()->gravity);
00292   a.Push(GameMode::GetInstance()->safe_fall);
00293   a.Push(GameMode::GetInstance()->damage_per_fall_unit);
00294   a.Push((int)GameMode::GetInstance()->duration_move_player);
00295   a.Push(GameMode::GetInstance()->allow_character_selection);
00296   a.Push((int)GameMode::GetInstance()->character.init_energy);
00297   a.Push((int)GameMode::GetInstance()->character.max_energy);
00298   a.Push((int)GameMode::GetInstance()->character.mass);
00299   a.Push(GameMode::GetInstance()->character.air_resist_factor);
00300   a.Push((int)GameMode::GetInstance()->character.jump_strength);
00301   a.Push(GameMode::GetInstance()->character.jump_angle);
00302   a.Push((int)GameMode::GetInstance()->character.super_jump_strength);
00303   a.Push(GameMode::GetInstance()->character.super_jump_angle);
00304   a.Push((int)GameMode::GetInstance()->character.back_jump_strength);
00305   a.Push(GameMode::GetInstance()->character.back_jump_angle);
00306   network.SendAction(&a);
00307 }
00308 
00309 // TODO: Move this into network/distant_cpu.cpp
00310 void Action_NewTeam (Action *a)
00311 {
00312   ConfigTeam the_team;
00313 
00314   the_team.id = a->PopString();
00315   the_team.player_name = a->PopString();
00316   the_team.nb_characters = uint(a->PopInt());
00317 
00318   teams_list.AddTeam (the_team);
00319 
00320   network.network_menu->AddTeamCallback(the_team.id);
00321 }
00322 
00323 void Action_UpdateTeam (Action *a)
00324 {
00325   ConfigTeam the_team;
00326 
00327   the_team.id = a->PopString();
00328   the_team.player_name = a->PopString();
00329   the_team.nb_characters = uint(a->PopInt());
00330 
00331   teams_list.UpdateTeam (the_team);
00332 
00333   network.network_menu->UpdateTeamCallback(the_team.id);
00334 }
00335 
00336 // TODO: Move this into network/distant_cpu.cpp
00337 void Action_DelTeam (Action *a)
00338 {
00339   std::string team = a->PopString();
00340   teams_list.DelTeam (team);
00341   network.network_menu->DelTeamCallback(team);
00342 }
00343 
00344 // TODO: Move this into network/distant_cpu.cpp
00345 void Action_ChatMessage (Action *a)
00346 {
00347   if(Game::GetInstance()->IsGameLaunched())
00348     //Add message to chat session in Game
00349     //    GameLoop::GetInstance()->chatsession.chat->AddText(a->PopString());
00350     GameLoop::GetInstance()->chatsession.NewMessage(a->PopString());
00351   else
00352     //Network Menu
00353     network.network_menu->ReceiveMsgCallback(a->PopString());
00354 }
00355 
00356 void Action_ChangeTeam (Action *a)
00357 {
00358   teams_list.SetActive (a->PopString());
00359   ActiveTeam().PrepareTurn();
00360   assert (!ActiveCharacter().IsDead());
00361 }
00362 
00363 void Action_AskVersion (Action *a)
00364 {
00365   if (!network.IsClient()) return;
00366   ActionHandler::GetInstance()->NewAction(new Action(Action::ACTION_SEND_VERSION, Constants::VERSION));
00367 }
00368 
00369 void Action_SendVersion (Action *a)
00370 {
00371   if (!network.IsServer()) return;
00372   std::string version= a->PopString();
00373   if (version != Constants::VERSION)
00374   {
00375     Error(Format(_("Wormux versions are differents : client=%s, server=%s."),
00376     version.c_str(), Constants::VERSION.c_str()));
00377   }
00378 }
00379 
00380 void Action_SendRandom (Action *a)
00381 {
00382   if (!network.IsClient()) return;
00383   randomSync.AddToTable(a->PopDouble());
00384 }
00385 
00386 void Action_SupertuxState (Action *a)
00387 {
00388   assert(ActiveTeam().GetWeaponType() == Weapon::WEAPON_SUPERTUX);
00389   WeaponLauncher* launcher = static_cast<WeaponLauncher*>(&(ActiveTeam().AccessWeapon()));
00390   SuperTux* tux = static_cast<SuperTux*>(launcher->GetProjectile());
00391 
00392   double x, y;
00393 
00394   tux->SetAngle(a->PopDouble());
00395   x = a->PopDouble();
00396   y = a->PopDouble();
00397   tux->SetPhysXY(x, y);
00398   tux->SetSpeedXY(Point2d(0,0));
00399 }
00400 
00401 void Action_SyncBegin (Action *a)
00402 {
00403   assert(!network.sync_lock);
00404   network.sync_lock = true;
00405 }
00406 
00407 void Action_SyncEnd (Action *a)
00408 {
00409   assert(network.sync_lock);
00410   network.sync_lock = false;
00411 }
00412 
00413 // Nothing to do here. Just for time synchronisation
00414 void Action_Ping(Action *a)
00415 {
00416 }
00417 
00418 void Action_Explosion (Action *a)
00419 {
00420   Point2i pos;
00421   ExplosiveWeaponConfig config;
00422 
00423   pos.x = a->PopInt();
00424   pos.y = a->PopInt();
00425   config.explosion_range = a->PopInt();
00426   config.particle_range = a->PopInt();
00427   config.damage = a->PopInt();
00428   config.blast_range = a->PopDouble();
00429   config.blast_force = a->PopDouble();
00430   std::string son = a->PopString();
00431   bool fire_particle = a->PopInt();
00432   ParticleEngine::ESmokeStyle smoke = (ParticleEngine::ESmokeStyle)a->PopInt();
00433 
00434   ApplyExplosion_common(pos, config, son, fire_particle, smoke);
00435 }
00436 
00437 void Action_SetTarget (Action *a)
00438 {
00439   MSG_DEBUG("action.handler", "Set target by clicking");
00440 
00441   Point2i target;
00442   target.x = a->PopInt();
00443   target.y = a->PopInt();
00444 
00445   ActiveTeam().AccessWeapon().ChooseTarget (target);
00446 }
00447 
00448 void Action_SetTimeout (Action *a)
00449 {
00450   WeaponLauncher* launcher = dynamic_cast<WeaponLauncher*>(&(ActiveTeam().AccessWeapon()));
00451   assert(launcher != NULL);
00452   launcher->GetProjectile()->m_timeout_modifier = a->PopInt();
00453 }
00454 
00455 void Action_ConstructionUp (Action *a)
00456 {
00457   Construct* launcher = dynamic_cast<Construct*>(&(ActiveTeam().AccessWeapon()));
00458   assert(launcher != NULL);
00459   launcher->Up();
00460 }
00461 
00462 void Action_ConstructionDown (Action *a)
00463 {
00464   Construct* launcher = dynamic_cast<Construct*>(&(ActiveTeam().AccessWeapon()));
00465   assert(launcher != NULL);
00466   launcher->Down();
00467 }
00468 
00469 void Action_WeaponStopUse(Action *a)
00470 {
00471   ActiveTeam().AccessWeapon().ActionStopUse();
00472 }
00473 
00474 void Action_Nickname(Action *a)
00475 {
00476 
00477 }
00478 
00479 void Action_Pause(Action *a)
00480 {
00481   // Toggle pause
00482   Game::GetInstance()->Pause();
00483 }
00484 
00485 void ActionHandler::ExecActions()
00486 {
00487   Action * a;
00488   std::list<Action*> to_remove;
00489   std::list<Action*>::iterator it;
00490   assert(mutex!=NULL);
00491   for(it = queue.begin(); it != queue.end() ; ++it)
00492   {
00493     SDL_LockMutex(mutex);
00494     a = (*it);
00495     Time::GetInstance()->RefreshMaxTime((*it)->GetTimestamp());
00496     // If action is in the future, wait for next refresh
00497     if((*it)->GetTimestamp() > Time::GetInstance()->Read()) {
00498       SDL_UnlockMutex(mutex);
00499       continue;
00500     }
00501     SDL_UnlockMutex(mutex);
00502     Exec ((*it));
00503     to_remove.push_back((*it));
00504   }
00505   while(to_remove.size() != 0)
00506   {
00507     a = to_remove.front();
00508     to_remove.pop_front();
00509     queue.remove(a);
00510     delete(a);
00511   }
00512 }
00513 
00514 void ActionHandler::NewAction(Action* a, bool repeat_to_network)
00515 {
00516   assert(mutex!=NULL);
00517   SDL_LockMutex(mutex);
00518   //  MSG_DEBUG("action.handler","New action : %s",a.out());
00519   //  std::cout << "New action " << a->GetType() << std::endl ;
00520   queue.push_back(a);
00521   //  std::cout << "  queue_size " << queue.size() << std::endl;
00522   SDL_UnlockMutex(mutex);
00523   if (repeat_to_network) network.SendAction(a);
00524 }
00525 
00526 void ActionHandler::Register (Action::Action_t action,
00527                                       const std::string &name,callback_t fct)
00528 {
00529   handler[action] = fct;
00530   action_name[action] = name;
00531 }
00532 
00533 void ActionHandler::Exec(Action *a)
00534 {
00535   MSG_DEBUG("action_handler", "Executing action %s",GetActionName(a->GetType()).c_str());
00536   handler_it it=handler.find(a->GetType());
00537   assert(it != handler.end());
00538   (*it->second) (a);
00539 }
00540 
00541 std::string ActionHandler::GetActionName (Action::Action_t action)
00542 {
00543   assert(mutex!=NULL);
00544   SDL_LockMutex(mutex);
00545   name_it it=action_name.find(action);
00546   assert(it != action_name.end());
00547   SDL_UnlockMutex(mutex);
00548   return it->second;
00549 }
00550 
00551 ActionHandler::ActionHandler()
00552 {
00553   mutex = SDL_CreateMutex();
00554   SDL_LockMutex(mutex);
00555   Register (Action::ACTION_MOVE_LEFT, "move_left", &Action_MoveLeft);
00556   Register (Action::ACTION_MOVE_RIGHT, "move_right", &Action_MoveRight);
00557   Register (Action::ACTION_UP, "up", &Action_Up);
00558   Register (Action::ACTION_DOWN, "down", &Action_Down);
00559   Register (Action::ACTION_JUMP, "jump", &Action_Jump);
00560   Register (Action::ACTION_HIGH_JUMP, "super_jump", &Action_HighJump);
00561   Register (Action::ACTION_BACK_JUMP, "back_jump", &Action_BackJump);
00562   Register (Action::ACTION_SHOOT, "shoot", &Action_Shoot);
00563   Register (Action::ACTION_CHANGE_WEAPON, "change_weapon", &Action_ChangeWeapon);
00564   Register (Action::ACTION_WIND, "wind", &Action_Wind);
00565   Register (Action::ACTION_NEXT_CHARACTER, "next_character", &Action_NextCharacter);
00566   Register (Action::ACTION_CHANGE_CHARACTER, "change_character", &Action_ChangeCharacter);
00567   Register (Action::ACTION_SET_GAME_MODE, "set_game_mode", &Action_SetGameMode);
00568   Register (Action::ACTION_SET_MAP, "set_map", &Action_SetMap);
00569   Register (Action::ACTION_UPDATE_TEAM, "update_team", &Action_UpdateTeam);
00570   Register (Action::ACTION_NEW_TEAM, "new_team", &Action_NewTeam);
00571   Register (Action::ACTION_DEL_TEAM, "del_team", &Action_DelTeam);
00572   Register (Action::ACTION_CHANGE_TEAM, "change_team", &Action_ChangeTeam);
00573   Register (Action::ACTION_SET_CHARACTER_PHYSICS, "set_character_physics", &Action_SetCharacterPhysics);
00574   Register (Action::ACTION_SET_SKIN, "set_skin", &Action_SetSkin);
00575   Register (Action::ACTION_SET_CHARACTER_DIRECTION, "set_character_direction", &Action_SetCharacterDirection);
00576   Register (Action::ACTION_CHANGE_STATE, "change_state", &Action_ChangeState);
00577   Register (Action::ACTION_ASK_VERSION, "ask_version", &Action_AskVersion);
00578   Register (Action::ACTION_SEND_VERSION, "send_version", &Action_SendVersion);
00579   Register (Action::ACTION_SEND_RANDOM, "send_random", &Action_SendRandom);
00580   Register (Action::ACTION_PING, "ping", &Action_Ping);
00581   Register (Action::ACTION_SYNC_BEGIN, "sync_begin", &Action_SyncBegin);
00582   Register (Action::ACTION_SYNC_END, "sync_end", &Action_SyncEnd);
00583   Register (Action::ACTION_EXPLOSION, "explosion", &Action_Explosion);
00584   Register (Action::ACTION_SET_TARGET, "set_target", &Action_SetTarget);
00585   Register (Action::ACTION_SUPERTUX_STATE, "supertux_state", &Action_SupertuxState);
00586   Register (Action::ACTION_SET_TIMEOUT, "set_timeout", &Action_SetTimeout);
00587   Register (Action::ACTION_CONSTRUCTION_UP, "construction_up", &Action_ConstructionUp);
00588   Register (Action::ACTION_CONSTRUCTION_DOWN, "construction_down", &Action_ConstructionDown);
00589   Register (Action::ACTION_WEAPON_STOP_USE, "weapon_stop_use", &Action_WeaponStopUse);
00590   Register (Action::ACTION_SET_CHARACTER_ENERGY, "set_character_energy", &Action_SetCharacterEnergy);
00591   Register (Action::ACTION_CHAT_MESSAGE, "chat_message", Action_ChatMessage);
00592   Register (Action::ACTION_NICKNAME, "nickname", Action_Nickname);
00593   Register (Action::ACTION_PAUSE, "pause", Action_Pause);
00594   SDL_UnlockMutex(mutex);
00595 }
00596 

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