/* Copyright (C) 1998 Pyrosoft Inc. (www.pyrosoftgames.com), Matthew Bogue This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "GameControlRulesDaemon.hpp" #include "GameManager.hpp" #include "GameConfig.hpp" #include "PlayerInterface.hpp" #include "ObjectiveInterface.hpp" #include "MapsManager.hpp" #include "ConsoleInterface.hpp" #include "ChatInterface.hpp" #include "NetworkState.hpp" #include "SystemNetMessage.hpp" #include "GameControlNetMessage.hpp" #include "Server.hpp" #include "NetworkServer.hpp" #include "Client.hpp" #include "ServerConnectDaemon.hpp" #include "Desktop.hpp" #include "ProgressView.hpp" #include "Util/Log.hpp" enum { _map_cycle_server_state_idle, _map_cycle_server_state_display_endgame_views, _map_cycle_server_state_cycle_next_map, _map_cycle_server_state_load_map, _map_cycle_server_state_wait_for_client_map_load, _map_cycle_server_state_respawn_players }; enum { _map_cycle_client_idle, _map_cycle_client_start_map_load, _map_cycle_client_load_map, _map_cycle_client_wait_for_respawn_ack }; enum { _execution_mode_loop_back_server, _execution_mode_dedicated_server }; enum { _game_state_idle, _game_state_in_progress, _game_state_completed }; int GameControlRulesDaemon::execution_mode = _execution_mode_loop_back_server; unsigned char GameControlRulesDaemon::game_state = _game_state_idle; std::string GameControlRulesDaemon::nextmap = ""; #define _MAP_CYCLE_ENDGAME_WAIT_PERIOD (20) // seconds #define _MAP_CYCLE_MAP_LOAD_WAIT_PERIOD (7) // seconds int GameControlRulesDaemon::map_cycle_fsm_server_state = _map_cycle_server_state_idle; Timer GameControlRulesDaemon::map_cycle_fsm_server_endgame_timer; Timer GameControlRulesDaemon::map_cycle_fsm_server_map_load_timer; int GameControlRulesDaemon::map_cycle_fsm_client_state = _map_cycle_client_idle; bool GameControlRulesDaemon::map_cycle_fsm_client_respawn_ack_flag = false; char GameControlRulesDaemon::map_cycle_fsm_client_map_name[256]; //----------------------------------------------------------------- void GameControlRulesDaemon::setStateServerInProgress() { GameControlRulesDaemon::game_state = _game_state_in_progress; } //----------------------------------------------------------------- void GameControlRulesDaemon::setDedicatedServer() { GameControlRulesDaemon::execution_mode = _execution_mode_dedicated_server; } //----------------------------------------------------------------- void GameControlRulesDaemon::mapCycleFsmClient() { switch( map_cycle_fsm_client_state ) { case _map_cycle_client_idle : return; case _map_cycle_client_start_map_load : { progressView->open(); GameManager::shutdownParticleSystems(); ObjectiveInterface::resetLogic(); gameconfig->map = map_cycle_fsm_client_map_name; char buf[256]; snprintf(buf, sizeof(buf), "Next Map '%s'.", gameconfig->map.c_str()); progressView->scrollAndUpdate( buf); progressView->scrollAndUpdate( "Loading Game Map ..." ); try { GameManager::startGameMapLoad(gameconfig->map.c_str(), 16); } catch(std::exception& e) { progressView->scrollAndUpdate("Error while loading map:"); progressView->scrollAndUpdate(e.what()); map_cycle_fsm_client_state = _map_cycle_client_idle; return; } GameManager::resetGameLogic(); map_cycle_fsm_client_state = _map_cycle_client_load_map; return; } break; case _map_cycle_client_load_map : { int percent_complete; char str_buf[128]; if ( GameManager::gameMapLoad( &percent_complete ) == false ) { map_cycle_fsm_client_state = _map_cycle_client_wait_for_respawn_ack; sprintf( str_buf, "Loading Game Map ... (%d%%)", percent_complete); progressView->update( str_buf ); progressView->scrollAndUpdate( "Waiting to respawn ..." ); } else { sprintf( str_buf, "Loading Game Map ... (%d%%)", percent_complete); progressView->update( str_buf ); } return; } case _map_cycle_client_wait_for_respawn_ack : { if( map_cycle_fsm_client_respawn_ack_flag == true ) { progressView->toggleGameView(); map_cycle_fsm_client_respawn_ack_flag = false; map_cycle_fsm_client_state = _map_cycle_client_idle; } return; } break; } // ** switch } void GameControlRulesDaemon::mapCycleFsmServer() { switch( map_cycle_fsm_server_state ) { case _map_cycle_server_state_idle: break; case _map_cycle_server_state_display_endgame_views: { ChatInterface::setMessageScopeServer(); ChatInterface::sendCurrentMessage("Round is over"); SystemViewControl view_control; ServerConnectDaemon::lockConnectProcess(); view_control.set("RankView", _view_control_flag_visible_on | _view_control_flag_close_all ); if ( GameControlRulesDaemon::execution_mode == _execution_mode_loop_back_server ) { Desktop::setVisibilityAllWindows(false); Desktop::setVisibility("GameView", true); Desktop::setVisibility("RankView", true ); } SERVER->sendMessage(&view_control, sizeof(SystemViewControl)); map_cycle_fsm_server_endgame_timer.changePeriod( _MAP_CYCLE_ENDGAME_WAIT_PERIOD ); map_cycle_fsm_server_endgame_timer.reset(); map_cycle_fsm_server_state = _map_cycle_server_state_cycle_next_map; } break; case _map_cycle_server_state_cycle_next_map : { if ( map_cycle_fsm_server_endgame_timer.count() && (ServerConnectDaemon::isConnecting() == false) ) { GameManager::shutdownParticleSystems(); if(nextmap != "") { gameconfig->map = nextmap; nextmap = ""; } else { gameconfig->map = MapsManager::getNextMap(gameconfig->map); } ConsoleInterface::postMessage("loading map '%s'.", gameconfig->map.c_str()); GameControlCycleMap cycle_map_mesg; cycle_map_mesg.set( gameconfig->map.c_str() ); SERVER->sendMessage( &cycle_map_mesg, sizeof( GameControlCycleMap )); if ( GameControlRulesDaemon::execution_mode == _execution_mode_dedicated_server ) { ObjectiveInterface::resetLogic(); GameManager::dedicatedLoadGameMap( gameconfig->map.c_str()); GameManager::resetGameLogic(); map_cycle_fsm_server_map_load_timer.changePeriod(_MAP_CYCLE_MAP_LOAD_WAIT_PERIOD); map_cycle_fsm_server_map_load_timer.reset(); map_cycle_fsm_server_state = _map_cycle_server_state_wait_for_client_map_load; } else { progressView->open(); progressView->scrollAndUpdate( "Loading Game Map ..." ); ObjectiveInterface::resetLogic(); try { GameManager::startGameMapLoad (gameconfig->map.c_str(), 16); } catch(std::exception& e) { progressView->scrollAndUpdate( "Error while loading map:"); progressView->scrollAndUpdate(e.what()); map_cycle_fsm_server_state = _map_cycle_server_state_idle; return; } GameManager::resetGameLogic(); map_cycle_fsm_server_state = _map_cycle_server_state_load_map; return; } } } break; case _map_cycle_server_state_load_map : { int percent_complete; char str_buf[128]; if ( GameManager::gameMapLoad( &percent_complete ) == false ) { map_cycle_fsm_server_state = _map_cycle_server_state_respawn_players; } sprintf( str_buf, "Loading Game Map ... (%d%%)", percent_complete); progressView->update( str_buf ); } break; case _map_cycle_server_state_wait_for_client_map_load : { if ( map_cycle_fsm_server_map_load_timer.count() ) { ConsoleInterface::postMessage("game started."); map_cycle_fsm_server_state = _map_cycle_server_state_respawn_players; } } break; case _map_cycle_server_state_respawn_players : { SystemResetGameLogic reset_game_logic_mesg; GameManager::resetGameLogic(); SERVER->sendMessage( &reset_game_logic_mesg, sizeof(SystemResetGameLogic)); GameManager::respawnAllPlayers(); PlayerInterface::unlockPlayerStats(); GameControlRulesDaemon::game_state = _game_state_in_progress; progressView->toggleGameView(); GameControlCycleRespawnAck respawn_ack_mesg; SERVER->sendMessage( &respawn_ack_mesg, sizeof(GameControlCycleRespawnAck)); map_cycle_fsm_server_state = _map_cycle_server_state_idle; ServerConnectDaemon::unlockConnectProcess(); } break; } // ** switch } void GameControlRulesDaemon::onTimelimitGameCompleted() { PlayerInterface::lockPlayerStats(); map_cycle_fsm_server_state = _map_cycle_server_state_display_endgame_views; GameControlRulesDaemon::game_state = _game_state_completed; } void GameControlRulesDaemon::onFraglimitGameCompleted() { PlayerInterface::lockPlayerStats(); map_cycle_fsm_server_state = _map_cycle_server_state_display_endgame_views; GameControlRulesDaemon::game_state = _game_state_completed; } void GameControlRulesDaemon::onObjectiveGameCompleted() { PlayerInterface::lockPlayerStats(); map_cycle_fsm_server_state = _map_cycle_server_state_display_endgame_views; GameControlRulesDaemon::game_state = _game_state_completed; } void GameControlRulesDaemon::forceMapChange(std::string _nextmap) { nextmap = _nextmap; PlayerInterface::lockPlayerStats(); map_cycle_fsm_server_state = _map_cycle_server_state_display_endgame_views; GameControlRulesDaemon::game_state = _game_state_completed; } void GameControlRulesDaemon::checkGameRules() { PlayerState *player_state; if ( (GameControlRulesDaemon::game_state == _game_state_in_progress) && (NetworkState::status == _network_state_server) ) { unsigned char game_type; game_type = gameconfig->gametype; switch( game_type ) { case _gametype_timelimit : { int game_minutes = GameManager::getGameTime() / 60; if( game_minutes >= gameconfig->timelimit ) { onTimelimitGameCompleted(); } } case _gametype_fraglimit : { if ( PlayerInterface::testRuleScoreLimit( gameconfig->fraglimit, &player_state ) == true ) { onFraglimitGameCompleted(); } } break; case _gametype_objective: float ratio = (float) gameconfig->objectiveoccupationpercentage / 100.0; if (PlayerInterface::testRuleObjectiveRatio( ratio, &player_state)) { onObjectiveGameCompleted( ); } break; } // ** switch // ** Check for Player Respawns ** bool respawn_rule_complete = false; while( respawn_rule_complete == false ) { if ( PlayerInterface::testRulePlayerRespawn( &respawn_rule_complete, &player_state ) ) { GameManager::spawnPlayer( player_state ); } // ** if testRulePlayerRespawn } // ** while } } void GameControlRulesDaemon::netMessageCycleMap(const NetMessage* message) { GameControlCycleMap *cycle_map_mesg; cycle_map_mesg = (GameControlCycleMap *) message; snprintf(map_cycle_fsm_client_map_name, 256, cycle_map_mesg->map_name); map_cycle_fsm_client_state = _map_cycle_client_start_map_load; } void GameControlRulesDaemon::netMessageCycleRespawnAck(const NetMessage* ) { map_cycle_fsm_client_respawn_ack_flag = true; } void GameControlRulesDaemon::processNetMessage(const NetMessage* message) { switch(message->message_id) { case _net_message_id_game_control_cycle_map : netMessageCycleMap(message); break; case _net_message_id_game_control_cycle_respawn_ack : netMessageCycleRespawnAck(message); break; default: LOGGER.warning( "Received GameControlRulesMessage with unknown id (%d-%d)", message->message_class, message->message_id); break; } } void GameControlRulesDaemon::updateGameControlFlow() { if ( NetworkState::status == _network_state_server ) { mapCycleFsmServer(); } else { mapCycleFsmClient(); } checkGameRules(); } void GameControlRulesDaemon::mapLoadFailureResponse(int result_code, const char *map_name) { char str_buf[128]; if( result_code == _mapload_result_no_map_file ) { sprintf( str_buf, "MAP %s NOT FOUND!", map_name ); progressView->scrollAndUpdate( str_buf); } else if( result_code == _mapload_result_no_wad_file ) { progressView->scrollAndUpdate( "MAP TILE SET NOT FOUND!" ); } }