Esempio n. 1
0
void TimeLimit::Event ( bz_EventData *eventData )
{
  switch(eventData->eventType)
  {
    case bz_ePlayerJoinEvent: {
	    bz_APIIntList *playerList = bz_newIntList();
	    bz_getPlayerIndexList (playerList);

	    // if it's the first player that joins , then reset the time to default
	    if ( playerList->size() == 1 && bz_isTimeManualStart() && !bz_isCountDownActive()  && !bz_isCountDownInProgress()) {
	      bz_setTimeLimit(saveTimeLimit);
	    }
    }
     break;

	//reset the time to default at gameover
    case bz_eGameEndEvent: {
	    bz_setTimeLimit(saveTimeLimit);
    }
     break;

    default: {
		// do nothing
    }
  }

}
Esempio n. 2
0
void observerChat::Event ( bz_EventData *eventData )
{
  switch (eventData->eventType)
  {
  case bz_eRawChatMessageEvent:
    {
      bz_ChatEventData_V1 *data = (bz_ChatEventData_V1*)eventData;
      int from = data->from;
      bool isObserver = bz_getPlayerTeam(from) == eObservers;
      bool canSpawn = bz_hasPerm(from,bz_perm_spawn);
      const char* duringTheGame = "";

      if (!isObserver && canSpawn) return;
      if (data->to != BZ_ALLUSERS && (isObserver || data->team == eNoTeam)) return;
      if (bz_hasPerm(from,permName) || bz_getAdmin(from)) return;

      std::string variableValue = makelower(bz_getBZDBString(variableName).c_str());
      if (variableValue == "off" || variableValue == "disable" || variableValue == "disabled" || variableValue == "no") return;
      else if (!(variableValue == "on" || variableValue == "always" || variableValue == "alwayson" || variableValue == "enable" || variableValue == "enabled" || variableValue == "yes")) {
        if (!bz_isCountDownActive()) return;
        duringTheGame = " during the game";
      }

      bz_sendTextMessagef(BZ_SERVER,from,"You are not allowed to send global messages%s.",duringTheGame);
      bz_sendTextMessagef(BZ_SERVER,from,"Please use observer chat only.");
      data->message = "";
    }
    break;
  default:
    break;
  }
}
Esempio n. 3
0
bool leagueOverSeer::SlashCommand(int playerID, bz_ApiString command, bz_ApiString /*message*/, bz_APIStringList *params)
{
    int timeToStart = atoi(params->get(0).c_str());
    bz_BasePlayerRecord *playerData = bz_getPlayerByIndex(playerID);

    if (command == "official") //Someone used the /official command
    {
        if (playerData->team == eObservers) //Observers can't start matches
            bz_sendTextMessage(BZ_SERVER, playerID, "Observers are not allowed to start matches.");
        else if ((bz_getTeamCount(eRedTeam) < 2 && bz_getTeamPlayerLimit(eRedTeam) > 0) ||
                (bz_getTeamCount(eGreenTeam) < 2 && bz_getTeamPlayerLimit(eGreenTeam) > 0) ||
                (bz_getTeamCount(eBlueTeam) < 2 && bz_getTeamPlayerLimit(eBlueTeam) > 0) ||
                (bz_getTeamCount(ePurpleTeam) < 2 && bz_getTeamPlayerLimit(ePurpleTeam) > 0)) //An official match cannot be 1v1 or 2v1
            bz_sendTextMessage(BZ_SERVER, playerID, "You may not have an official match with less than 2 players per team.");
        else if (funMatch) //A fun match cannot be declared an official match
            bz_sendTextMessage(BZ_SERVER,playerID,"Fun matches cannot be turned into official matches.");
        else if (!playerData->verified || !bz_hasPerm(playerID,"spawn")) //If they can't spawn, they aren't a league player so they can't start a match
            bz_sendTextMessage(BZ_SERVER,playerID,"Only registered league players may start an official match.");
        else if (bz_isCountDownActive() || bz_isCountDownInProgress()) //A countdown is in progress already
            bz_sendTextMessage(BZ_SERVER,playerID,"There is currently a countdown active, you may not start another.");
        else if (playerData->verified && playerData->team != eObservers && bz_hasPerm(playerID,"spawn") && !bz_isCountDownActive() && !funMatch) //Check the user is not an obs and is a league member
        {
            officialMatch = true; //Notify the plugin that the match is official
            bz_debugMessagef(DEBUG, "DEBUG :: League Over Seer :: Official match started by %s (%s).", playerData->callsign.c_str(), playerData->ipAddress.c_str());
            bz_sendTextMessagef(BZ_SERVER, BZ_ALLUSERS, "Official match started by %s.", playerData->callsign.c_str());

            if (timeToStart <= 120 && timeToStart > 5)
                bz_startCountdown (timeToStart, bz_getTimeLimit(), "Server"); //Start the countdown with a custom countdown time limit under 2 minutes
            else
                bz_startCountdown (10, bz_getTimeLimit(), "Server"); //Start the countdown for the official match
        }
        else
            bz_sendTextMessage(BZ_SERVER, playerID, "You do not have permission to run the /official command.");

        return true;
    }
    else if (command == "fm") //Someone uses the /fm command
    {
        if (bz_isCountDownActive() || bz_isCountDownInProgress() || funMatch || officialMatch) //There is already a countdown
            bz_sendTextMessage(BZ_SERVER, playerID, "There is currently a countdown active, you may not start another.");
        else if (playerData->team == eObservers) //Observers can't start matches
            bz_sendTextMessage(BZ_SERVER,playerID,"Observers are not allowed to start matches.");
        else if (!playerData->verified || !bz_hasPerm(playerID,"spawn")) //If they can't spawn, they aren't a league player so they can't start a match
            bz_sendTextMessage(BZ_SERVER,playerID,"Only registered league players may start an official match.");
        else if (!bz_isCountDownActive() && playerData->team != eObservers && bz_hasPerm(playerID,"spawn") && playerData->verified && !officialMatch)
        {
            funMatch = true; //It's a fun match

            bz_debugMessagef(DEBUG, "DEBUG :: League Over Seer :: Fun match started by %s (%s).", playerData->callsign.c_str(), playerData->ipAddress.c_str());
            bz_sendTextMessagef(BZ_SERVER, BZ_ALLUSERS, "Fun match started by %s.", playerData->callsign.c_str());

            if (timeToStart <= 120 && timeToStart > 5)
                bz_startCountdown (timeToStart, bz_getTimeLimit(), "Server"); //Start the countdown with a custom countdown time limit under 2 minutes
            else
                bz_startCountdown (10, bz_getTimeLimit(), "Server"); //Start the countdown for the official match
        }
        else
            bz_sendTextMessage(BZ_SERVER,playerID,"You do not have permission to run the /fm command.");

        return true;
    }
    else if (command == "cancel")
    {
        if (bz_hasPerm(playerID,"spawn") && bz_isCountDownActive())
        {
            if (officialMatch)
            {
                bz_sendTextMessagef(BZ_SERVER, BZ_ALLUSERS, "Official match ended by %s", playerData->callsign.c_str());
                bz_debugMessagef(DEBUG, "DEBUG :: League Over Seer :: Match ended by %s (%s).", playerData->callsign.c_str(),playerData->ipAddress.c_str());
            }
            else
            {
                bz_sendTextMessagef(BZ_SERVER, BZ_ALLUSERS, "Fun match ended by %s", playerData->callsign.c_str());
                bz_debugMessagef(DEBUG, "DEBUG :: League Over Seer :: Match ended by %s (%s).", playerData->callsign.c_str(),playerData->ipAddress.c_str());
            }

            //Reset the server. Cleanly ends a match
            officialMatch = false;
            doNotReportMatch = true;
            funMatch = false;
            teamOnePoints = 0;
            teamTwoPoints = 0;

            //End the countdown
            if (bz_isCountDownActive())
                bz_gameOver(253, eObservers);
        }
        else if (!bz_isCountDownActive())
            bz_sendTextMessage(BZ_SERVER, playerID, "There is no match in progress to cancel.");
        else //Not a league player
            bz_sendTextMessage(BZ_SERVER, playerID, "You do not have permission to run the /cancel command.");

        return true;
    }
    else if (command == "finish")
    {
        if (bz_hasPerm(playerID,"spawn") && bz_isCountDownActive() && officialMatch)
        {
            bz_debugMessagef(DEBUG, "DEBUG :: Match Over Seer :: Official match ended early by %s (%s)", playerData->callsign.c_str(), playerData->ipAddress.c_str());
            bz_sendTextMessagef(BZ_SERVER, BZ_ALLUSERS, "Official match ended early by %s", playerData->callsign.c_str());

            doNotReportMatch = false; //To prevent reporting a canceled match, let plugin know the match was canceled

            //End the countdown
            if (bz_isCountDownActive())
                bz_gameOver(253, eObservers);
        }
        else if (!bz_isCountDownActive())
            bz_sendTextMessage(BZ_SERVER, playerID, "There is no match in progress to end.");
        else if (!officialMatch)
            bz_sendTextMessage(BZ_SERVER, playerID, "You cannot /finish a fun match. Use /cancel instead.");
        else //Not a league player
            bz_sendTextMessage(BZ_SERVER, playerID, "You do not have permission to run the /finish command.");

        return true;
    }
    else if (command == "pause")
    {
        if (bz_isCountDownActive() && bz_hasPerm(playerID,"spawn") && playerData->verified)
            bz_pauseCountdown(playerData->callsign.c_str());
        else if (!bz_isCountDownActive())
            bz_sendTextMessage(BZ_SERVER, playerID, "There is no active match to pause right now.");
        else
            bz_sendTextMessage(BZ_SERVER, playerID, "You are not have permission to run the /pause command.");

        return true;
    }
    else if (command == "resume")
    {
        if (bz_hasPerm(playerID,"spawn") && playerData->verified && bz_isCountDownActive())
            bz_resumeCountdown(playerData->callsign.c_str());
        else if (!bz_isCountDownActive())
            bz_sendTextMessage(BZ_SERVER, playerID, "The current match is not paused.");
        else
            bz_sendTextMessage(BZ_SERVER, playerID, "You are not have permission to run the /resume command.");

        return true;
    }
    else if (command == "spawn")
    {
        if (bz_hasPerm(playerID, "ban"))
        {
            if (params->size() > 0)
            {
                std::string callsignToLookup; //store the callsign we're going to search for

                for (unsigned int i = 0; i < params->size(); i++) //piece together the callsign from the slash command parameters
                {
                    callsignToLookup += params->get(i).c_str();
                    if (i != params->size() - 1) // so we don't stick a whitespace on the end
                        callsignToLookup += " "; // add a whitespace between each chat text parameter
                }

                if (std::string::npos != std::string(params->get(0).c_str()).find("#") && isValidPlayerID(atoi(std::string(params->get(0).c_str()).erase(0, 1).c_str())))
                {
                    bz_grantPerm(atoi(std::string(params->get(0).c_str()).erase(0, 1).c_str()), "spawn");
                    bz_sendTextMessagef(BZ_SERVER, eAdministrators, "%s gave spawn perms to %s", bz_getPlayerByIndex(playerID)->callsign.c_str(), bz_getPlayerByIndex(atoi(std::string(params->get(0).c_str()).substr(0, 1).c_str()))->callsign.c_str());
                }
                else if (isValidCallsign(callsignToLookup) >= 0)
                {
                    bz_grantPerm(isValidCallsign(callsignToLookup), "spawn");
                    bz_sendTextMessagef(BZ_SERVER, eAdministrators, "%s gave spawn perms to %s", bz_getPlayerByIndex(playerID)->callsign.c_str(), bz_getPlayerByIndex(isValidCallsign(callsignToLookup))->callsign.c_str());
                }
                else
                    bz_sendTextMessagef(BZ_SERVER, playerID, "player %s not found", params->get(0).c_str());
            }
            else
                bz_sendTextMessage(BZ_SERVER, playerID, "/spawn <player id or callsign>");
        }
        else if (!playerData->admin)
            bz_sendTextMessage(BZ_SERVER,playerID,"You do not have permission to use the /spawn command.");

        return true;
    }

    bz_freePlayerRecord(playerData);
    return false;
}
Esempio n. 4
0
void leagueOverSeer::Event(bz_EventData *eventData)
{
    switch (eventData->eventType)
    {
        case bz_eCaptureEvent: //Someone caps
        {
            bz_CTFCaptureEventData_V1 *capData = (bz_CTFCaptureEventData_V1*)eventData;

            if (officialMatch) //Only keep score if it's official
            {
                if (capData->teamCapping == teamOne) teamOnePoints++;
                else if (capData->teamCapping == teamTwo) teamTwoPoints++;
            }
        }
        break;

        case bz_eGameEndEvent: //A /gameover or a match has ended
        {
            //Clear the bool variables
            funMatch = false;
            matchStartTime = 0;
            matchParticipantsRecorded = false;

            if (doNotReportMatch && officialMatch) //The match was canceled via /gameover or /superkill and we do not want to report these matches
            {
                officialMatch = false; //Match is over
                doNotReportMatch = false; //Reset the variable for next usage
                teamOnePoints = 0;
                teamTwoPoints = 0;
                matchPlayers.clear();
                bz_debugMessage(DEBUG, "DEBUG :: League Over Seer :: Official match was not reported.");
                bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, "Official match was not reported.");
            }
            else if (officialMatch)
            {
                officialMatch = false; //Match is over
                time_t t = time(NULL); //Get the current time
                tm * now = gmtime(&t);
                char match_date[20];

                sprintf(match_date, "%02d-%02d-%02d %02d:%02d:%02d", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec); //Format the date to -> year-month-day hour:minute:second

                //Convert ints to std::string with std::ostringstream
                std::ostringstream teamOnePointsConversion;
                teamOnePointsConversion << (teamOnePoints);
                std::ostringstream teamTwoPointsConversion;
                teamTwoPointsConversion << (teamTwoPoints);
                std::ostringstream matchTimeConversion;
                matchTimeConversion << (matchDuration/60);

                //Keep references to values for quick reference
                std::string teamOnePointsFinal = teamOnePointsConversion.str();
                std::string teamTwoPointsFinal = teamTwoPointsConversion.str();
                std::string matchTimeFinal = matchTimeConversion.str();

                // Store match data in the logs
                bz_debugMessagef(DEBUG, "Match Data :: League Over Seer Match Report");
                bz_debugMessagef(DEBUG, "Match Data :: -----------------------------");
                bz_debugMessagef(DEBUG, "Match Data :: Match Time      : %s", match_date);
                bz_debugMessagef(DEBUG, "Match Data :: Duration        : %s", matchTimeFinal.c_str());
                bz_debugMessagef(DEBUG, "Match Data :: Team One Score  : %s", teamOnePointsFinal.c_str());
                bz_debugMessagef(DEBUG, "Match Data :: Team Two Score  : %s", teamTwoPointsFinal.c_str());

                // Start building POST data to be sent to the league website
                std::string matchToSend = "query=reportMatch";
                matchToSend += "&teamOneWins=" + std::string(bz_urlEncode(teamOnePointsFinal.c_str()));
                matchToSend += "&teamTwoWins=" + std::string(bz_urlEncode(teamTwoPointsFinal.c_str()));

                matchToSend += "&duration=" + std::string(bz_urlEncode(matchTimeFinal.c_str())) + "&matchTime=" + std::string(bz_urlEncode(match_date));

                if (rotLeague) //Only add this parameter if it's a rotational league such as Open League
                    matchToSend += "&mapPlayed=" + std::string(bz_urlEncode(map.c_str()));

                matchToSend += "&teamOnePlayers=";
                bz_debugMessagef(DEBUG, "Match Data :: Team One Players");

                for (unsigned int i = 0; i < matchPlayers.size(); i++) //Add all the red players to the match report
                {
                    if (matchPlayers.at(i).team == teamOne)
                    {
                        matchToSend += std::string(bz_urlEncode(matchPlayers.at(i).bzid.c_str())) + ",";
                        bz_debugMessagef(DEBUG, "Match Data ::  %s (%s)", matchPlayers.at(i).callsign.c_str(), matchPlayers.at(i).bzid.c_str());
                    }
                }

                matchToSend.erase(matchToSend.size() - 1);
                matchToSend += "&teamTwoPlayers=";
                bz_debugMessagef(DEBUG, "Match Data :: Team Two Players");

                for (unsigned int i = 0; i < matchPlayers.size(); i++) //Add all the red players to the match report
                {
                    if (matchPlayers.at(i).team == teamTwo)
                    {
                        matchToSend += std::string(bz_urlEncode(matchPlayers.at(i).bzid.c_str())) + ",";
                        bz_debugMessagef(DEBUG, "Match Data ::  %s (%s)", matchPlayers.at(i).callsign.c_str(), matchPlayers.at(i).bzid.c_str());
                    }
                }

                matchToSend.erase(matchToSend.size() - 1);

                bz_debugMessagef(DEBUG, "Match Data :: -----------------------------");
                bz_debugMessagef(DEBUG, "Match Data :: End of Match Report");
                bz_debugMessagef(DEBUG, "DEBUG :: League Over Seer :: Reporting match data...");
                bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, "Reporting match...");

                bz_addURLJob(LEAGUE_URL.c_str(), this, matchToSend.c_str()); //Send the match data to the league website

                //Clear all the structures and scores for next match
                matchPlayers.clear();
                teamOnePoints = 0;
                teamTwoPoints = 0;
            }
            else
                bz_debugMessage(DEBUG, "DEBUG :: League Over Seer :: Fun match was not reported.");
        }
        break;

        case bz_eGameStartEvent: //The countdown has started
        {
            if (officialMatch) //Don't waste memory if the match isn't official
            {
                //Set the team scores to zero just in case
                teamOnePoints = 0;
                teamTwoPoints = 0;
                matchDuration = bz_getTimeLimit();
                matchStartTime = bz_getCurrentTime();
                doNotReportMatch = false;
                matchPlayers.clear();
            }
        }
        break;

        case bz_eGetPlayerMotto: // Change the motto of a player when they join
        {
            bz_GetPlayerMottoData_V2* mottoEvent = (bz_GetPlayerMottoData_V2*)eventData;

            // Prepare the SQL query with the BZID of the player
            sqlite3_bind_text(getPlayerMotto, 1, mottoEvent->record->bzID.c_str(), -1, SQLITE_TRANSIENT);

            if (sqlite3_step(getPlayerMotto) == SQLITE_ROW) // If returns a team name, use it
                mottoEvent->motto = (const char*)sqlite3_column_text(getPlayerMotto, 0);
            else
                mottoEvent->motto = "";

            sqlite3_reset(getPlayerMotto); //Clear the prepared statement so it can be reused
        }

        case bz_ePlayerJoinEvent: //A player joins
        {
            bz_PlayerJoinPartEventData_V1 *joinData = (bz_PlayerJoinPartEventData_V1*)eventData;

            if (!joinData)
                return;

            if ((bz_isCountDownActive() || bz_isCountDownInProgress()) && officialMatch)
                bz_sendTextMessage(BZ_SERVER, joinData->playerID, "*** There is currently an official match in progress, please be respectful. ***");
            else if ((bz_isCountDownActive() || bz_isCountDownInProgress()) && funMatch)
                bz_sendTextMessage(BZ_SERVER, joinData->playerID, "*** There is currently a fun match in progress, please be respectful. ***");

            if (joinData->record->verified)
            {
                // Build the POST data for the URL job
                std::string teamMotto = "query=teamNameQuery";
                teamMotto += "&teamPlayers=" + std::string(joinData->record->bzID.c_str());

                bz_debugMessagef(DEBUG, "DEBUG :: League Over Seer :: Getting motto for %s...", joinData->record->callsign.c_str());

                bz_addURLJob(LEAGUE_URL.c_str(), this, teamMotto.c_str()); //Send the team update request to the league website
            }
        }
        break;

        case bz_eSlashCommandEvent: //Someone uses a slash command
        {
            bz_SlashCommandEventData_V1 *commandData = (bz_SlashCommandEventData_V1*)eventData;
            bz_BasePlayerRecord *playerData = bz_getPlayerByIndex(commandData->from);
            std::string command = commandData->message.c_str(); //Use std::string for quick reference

            if (strncmp("/gameover", commandData->message.c_str(), 9) == 0)
                bz_sendTextMessagef(BZ_SERVER, commandData->from, "** '/gameover' is disabled, please use /finish or /cancel instead **");
            else if (strncmp("/countdown pause", commandData->message.c_str(), 16) == 0)
                bz_sendTextMessagef(BZ_SERVER, commandData->from, "** '/countdown pause' is disabled, please use /pause instead **");
            else if (strncmp("/countdown resume", commandData->message.c_str(), 17 ) == 0)
                bz_sendTextMessagef(BZ_SERVER, commandData->from, "** '/countdown resume' is disabled, please use /resume instead **");
            else if (isdigit(atoi(commandData->message.c_str()) + 12))
                bz_sendTextMessage(BZ_SERVER, commandData->from, "** '/countdown TIME' is disabled, please use /official or /fm instead **");

            bz_freePlayerRecord(playerData);
        }
        break;

        case bz_eTickEvent: //Tick tock tick tock...
        {
            int totaltanks = bz_getTeamCount(eRogueTeam) + bz_getTeamCount(eRedTeam) + bz_getTeamCount(eGreenTeam) + bz_getTeamCount(eBlueTeam) + bz_getTeamCount(ePurpleTeam);

            if (totaltanks == 0)
            {
                //Incase a boolean gets messed up in the plugin, reset all the plugin variables when there are no players (Observers excluded)
                officialMatch = false;
                doNotReportMatch = false;
                funMatch = false;
                teamOnePoints = 0;
                teamTwoPoints = 0;

                //This should never happen but just incase the countdown is going when there are no tanks
                if (bz_isCountDownActive())
                    bz_gameOver(253, eObservers);
            }

            if (matchStartTime > 0 && matchStartTime + matchRollCall < bz_getCurrentTime() && officialMatch && !matchParticipantsRecorded)
            {
                bool invalidateRollCall = false;
                bz_APIIntList *playerList = bz_newIntList();
                bz_getPlayerIndexList(playerList);

                for (unsigned int i = 0; i < playerList->size(); i++)
                {
                    bz_BasePlayerRecord *playerRecord = bz_getPlayerByIndex(playerList->get(i));

                    if (bz_getPlayerTeam(playerList->get(i)) != eObservers) //If player is not an observer
                    {
                        playersInMatch currentPlayer;
                        currentPlayer.team = playerRecord->team; //Add team to structure
                        currentPlayer.callsign = playerRecord->callsign.c_str(); //Add team to structure
                        currentPlayer.bzid = playerRecord->bzID.c_str(); //Add bzid to structure

                        if (std::string(playerRecord->bzID.c_str()).empty())
                            invalidateRollCall = true;

                        matchPlayers.push_back(currentPlayer);
                    }

                    bz_freePlayerRecord(playerRecord);
                }

                bz_deleteIntList(playerList);

                if (invalidateRollCall && matchRollCall < matchDuration)
                {
                    bz_debugMessagef(DEBUG, "DEBUG :: League Over Seer :: Invalid player found on field at %i:%i.", (int)(matchRollCall/60), (int)(fmod(matchRollCall,60.0)));

                    matchParticipantsRecorded = false;
                    matchRollCall += 30;
                    matchPlayers.clear();
                }
                else
                    matchParticipantsRecorded = true;
            }
        }
        break;

        default:
        break;
    }
}
Esempio n. 5
0
bool TimeLimit::SlashCommand ( int playerID, bz_ApiString cmd, bz_ApiString, bz_APIStringList* cmdParams )
{

  if (strcasecmp (cmd.c_str(), "timelimit")) {
	return false;
  }

  // Check permissions
  if (! bz_hasPerm(playerID,"TIMELIMIT")) {
	bz_sendTextMessagef (BZ_SERVER, playerID, "You do not have permission to run the timelimit command");
	return true;
  }

  // If the server is not configured for manual countdown the timelimit
  // command can't be used
  if (! bz_isTimeManualStart()) {
    bz_sendTextMessagef (BZ_SERVER, playerID, "This server was not configured for manual clock countdowns");
    return true;
  }

  if (cmdParams->get(0).c_str()[0] == '\0') {
    bz_sendTextMessagef (BZ_SERVER, playerID, "Usage : /timelimit <minutes>|show|reset");
    return true;
  }

  // displaying the current timelimit
  if (strcasecmp(cmdParams->get(0).c_str(),"show") == 0 ) {
    bz_sendTextMessagef (BZ_SERVER, playerID,"Match duration is set to %.0f minute(s)",(bz_getTimeLimit() / 60));
    return true;
  }

  // check if there is already a countdown in progress or if a match is
  // already in progress
  if ( bz_isCountDownInProgress() ) {
    bz_sendTextMessagef (BZ_SERVER, playerID, "There is a countdown already in progress, match duration can't be changed now");
    return true;
  } else if ( bz_isCountDownActive() ) {
    bz_sendTextMessagef (BZ_SERVER, playerID, "A game is already in progress, match duration can't be changed now");
    return true;
    }

  bz_BasePlayerRecord *playerRecord;
  playerRecord = bz_getPlayerByIndex(playerID);

  // resets the timer to the default
  if (strcasecmp(cmdParams->get(0).c_str(),"reset") == 0 ) {
    bz_setTimeLimit(saveTimeLimit);
    bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "Match duration reset to %.0f minute(s) by %s",(bz_getTimeLimit() / 60),playerRecord->callsign.c_str());
    return true;
  }

  unsigned i, nonumber=0;

  for (i=0; i < strlen(cmdParams->get(0).c_str()); i++) {
     if (isdigit(cmdParams->get(0).c_str()[i]) == 0) nonumber=1;
  }

  if (nonumber == 0 ) {
    float limit = (float)atof(cmdParams->get(0).c_str());
	// Don't allow timelimit being equal or lower then 0
	if (limit > 0 ) {

	  if (! isValidTime(limit)) {

	showMatchDurations(playerID);
		return true;
      }

      bz_setTimeLimit(limit * 60);
      bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "Match duration set to %.0f minute(s) by %s",(bz_getTimeLimit() / 60),playerRecord->callsign.c_str());
    } else {
	  bz_sendTextMessagef (BZ_SERVER, playerID, "Match duration can't be equal or lower then 0");
		  return true;
      }
  } else {
	bz_sendTextMessagef (BZ_SERVER, playerID, "Not a correct value");
	    return true;
    }

  return true;

}
void LeagueOverseer::Event (bz_EventData *eventData)
{
    switch (eventData->eventType)
    {
        case bz_eAllowFlagGrab: // This event is called each time a player attempts to grab a flag
        {
            bz_AllowFlagGrabData_V1* allowFlagGrabData = (bz_AllowFlagGrabData_V1*)eventData;
            std::string              flagAbbr          = allowFlagGrabData->flagType;
            int                      playerID          = allowFlagGrabData->playerID;

            if (isPcProtectionEnabled()) // Is the server configured to protect against Pass Camping
            {
                // Check if the last capture was within the 'PC_PROTECTION_DELAY' amount of seconds
                if (LAST_CAP + getPcProtectionDelay() > bz_getCurrentTime())
                {
                    // Check to see if the flag being grabbed belongs to the team that just had their flag captured AND check
                    // to see if someone not from the victim team grabbed it
                    if ((getTeamTypeFromFlag(flagAbbr) == CAP_VICTIM_TEAM && bz_getPlayerTeam(playerID) != CAP_VICTIM_TEAM))
                    {
                        // Disallow the flag grab if it's being grabbed by an enemy right after a flag capture
                        allowFlagGrabData->allow = false;
                    }
                }
            }
        }
        break;

        case bz_eAllowSpawn: // This event is called before a player respawns
        {
            bz_AllowSpawnData_V2* allowSpawnData = (bz_AllowSpawnData_V2*)eventData;
            int                   playerID       = allowSpawnData->playerID;

            if (!pluginSettings.isGuestSpawningEnabled(getCurrentGameMode()) && !isLeagueMember(playerID))
            {
                // Disable their spawning privileges
                allowSpawnData->handled    = true;
                allowSpawnData->allow      = false;
                allowSpawnData->kickPlayer = false;

                sendPluginMessage(playerID, pluginSettings.getGuestSpawningMessage(getCurrentGameMode()));
            }
        }
        break;

        case bz_eBZDBChange: // This event is called each time a BZDB variable is changed
        {
            bz_BZDBChangeData_V1* bzdbData = (bz_BZDBChangeData_V1*)eventData;

            if (bzdbData->key == "_pcProtectionDelay")
            {
                // Save the proposed value in a variable for easy access
                int proposedValue = std::stoi(bzdbData->value.c_str());

                // Our PC protection delay should be between 3 and 30 seconds only, otherwise set it to the default 5 seconds
                if (proposedValue < 3 || proposedValue > 30)
                {
                    bz_setBZDBInt("_pcProtectionDelay", 5);
                }
            }
        }
        break;

        case bz_eCaptureEvent: // This event is called each time a team's flag has been captured
        {
            if (isMatchInProgress())
            {
                bz_CTFCaptureEventData_V1* captureData = (bz_CTFCaptureEventData_V1*)eventData;
                std::shared_ptr<bz_BasePlayerRecord> capperData(bz_getPlayerByIndex(captureData->playerCapping));

                // Keep score
                (captureData->teamCapping == TEAM_ONE) ? currentMatch.incrementTeamOneScore() : currentMatch.incrementTeamTwoScore();

                // Store data for PC Protection
                CAP_VICTIM_TEAM = captureData->teamCapped;
                CAP_WINNER_TEAM = captureData->teamCapping;
                LAST_CAP        = captureData->eventTime;

                logMessage(pluginSettings.getDebugLevel(), "debug", "%s captured the flag at %s",
                        capperData->callsign.c_str(), getMatchTime().c_str());
                logMessage(pluginSettings.getDebugLevel(), "debug", "Match Score %s [%i] vs %s [%i]",
                        currentMatch.getTeamOneName().c_str(), currentMatch.getTeamOneScore(),
                        currentMatch.getTeamTwoName().c_str(), currentMatch.getTeamTwoScore());

                CaptureMatchEvent capEvent = CaptureMatchEvent().setBZID(capperData->bzID.c_str())
                                                                .setTime(getMatchTime());

                // If it's an official match, save the team ID
                if (isOfficialMatch())
                {
                    int teamID = (captureData->teamCapping == TEAM_ONE) ? currentMatch.getTeamOneID() : currentMatch.getTeamTwoID();

                    capEvent.setTeamID(teamID);
                }

                capEvent.save();

                currentMatch.saveEvent(capEvent.getJsonObject());
                currentMatch.stats_flagCapture(captureData->playerCapping);

                logMessage(pluginSettings.getVerboseLevel(), "debug", "CaptureMatchEvent JSON -> %s", capEvent.toString());
            }
        }
        break;

        case bz_eGameEndEvent: // This event is called each time a game ends
        {
            logMessage(pluginSettings.getVerboseLevel(), "debug", "A match has ended.");

            // Get the current standard UTC time
            bz_Time stdTime;
            bz_getUTCtime(&stdTime);
            std::string recordingFileName;

            // Only save the recording buffer if we actually started recording when the match started
            if (RECORDING)
            {
                logMessage(pluginSettings.getVerboseLevel(), "debug", "Recording was in progress during the match.");

                std::stringstream recordingName;

                std::string _matchType = (isOfficialMatch()) ? "offi" : "fm",
                            _teamOneName = currentMatch.getTeamOneName(),
                            _teamTwoName = currentMatch.getTeamTwoName();

                // (offi|fm)-YYYYMMDD
                recordingName << _matchType << "-" << stdTime.year << formatInt("%02d", stdTime.month) << formatInt("%02d", stdTime.day);

                if (!currentMatch.isRosterEmpty())
                {
                    std::replace(_teamOneName.begin(), _teamOneName.end(), ' ', '_');
                    std::replace(_teamTwoName.begin(), _teamTwoName.end(), ' ', '_');

                    // Team_A-vs-Team_B
                    recordingName << "-" << _teamOneName << "-vs-" << _teamTwoName;
                }

                // -HHMM
                recordingName << "-" << formatInt("%02d", stdTime.hour) << formatInt("%02d", stdTime.minute);

                const std::string nameForHash = recordingName.str();
                std::string hash = bz_MD5(nameForHash.c_str());

                // -ACBD123
                recordingName << "-" << hash.substr(0, 7);

                if (currentMatch.matchCanceled())
                {
                    // -Canceled
                    recordingName << "-Canceled";
                }

                recordingName << ".rec";

                recordingFileName = recordingName.str();
                logMessage(pluginSettings.getVerboseLevel(), "debug", "Replay file will be named: %s", recordingFileName.c_str());

                // Save the recording buffer and stop recording
                bz_saveRecBuf(recordingFileName.c_str(), 0);
                bz_stopRecBuf();
                logMessage(pluginSettings.getVerboseLevel(), "debug", "Replay file has been saved and recording has stopped.");

                // We're no longer recording, so set the boolean and announce to players that the file has been saved
                RECORDING = false;
                bz_sendTextMessagef(BZ_SERVER, BZ_ALLUSERS, "Match saved as: %s", recordingFileName.c_str());
            }

            // Format the date to -> year-month-day hour:minute:second
            char matchDate[20];
            sprintf(matchDate, "%02d-%02d-%02d %02d:%02d:%02d", stdTime.year, stdTime.month, stdTime.day, stdTime.hour, stdTime.minute, stdTime.second);

            currentMatch.save(matchDate, recordingFileName);

            if (pluginSettings.isMatchReportEnabled())
            {
                if (!currentMatch.isRosterEmpty())
                {
                    MatchUrlRepo.set("query", "matchReport")
                                .set("data", bz_urlEncode(currentMatch.toString().c_str()))
                                .submit();

                    if (currentMatch.isFM())
                    {
                        // It was a fun match, so there is no need to do anything

                        logMessage(pluginSettings.getVerboseLevel(), "debug", "Fun match has completed.");
                    }
                    else if (currentMatch.matchCanceled())
                    {
                        // The match was canceled for some reason so output the reason to both the players and the server logs

                        logMessage(pluginSettings.getDebugLevel(), "debug", "%s", currentMatch.getCancelation().c_str());
                        bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, currentMatch.getCancelation().c_str());
                    }
                    else
                    {
                        logMessage(pluginSettings.getDebugLevel(), "debug", "Reporting match data...");
                        bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, "Reporting match...");

                        // Send the match data to the league website
                        MATCH_INFO_SENT = true;
                    }
                }
            }

            // Reset our match data
            currentMatch = Match();

            // Empty our list of players since we don't need a history
            activePlayerList.clear();
        }
        break;

        case bz_eGamePauseEvent:
        {
            bz_GamePauseResumeEventData_V2* gamePauseData = (bz_GamePauseResumeEventData_V2*)eventData;

            // Get the current UTC time
            MATCH_PAUSED = time(NULL);

            // Send the messages
            bz_sendTextMessagef(BZ_SERVER, BZ_ALLUSERS, "    with %s remaining.", getMatchTime().c_str());
            logMessage(pluginSettings.getVerboseLevel(), "debug", "Match paused at %s by %s.", getMatchTime().c_str(), bz_getPlayerCallsign(gamePauseData->playerID));

            PauseResumeMatchEvent pauseEvent = PauseResumeMatchEvent();

            pauseEvent.setState(true)
                      .setTime(getMatchTime())
                      .setBZID(getPlayerBZID(gamePauseData->playerID))
                      .save();

            currentMatch.saveEvent(pauseEvent.getJsonObject());

            logMessage(pluginSettings.getVerboseLevel(), "debug", "PauseResumeMatchEvent JSON -> %s", pauseEvent.toString());
        }
        break;

        case bz_eGameResumeEvent:
        {
            bz_GamePauseResumeEventData_V2* gameResumeData = (bz_GamePauseResumeEventData_V2*)eventData;

            // Get the current UTC time
            time_t now = time(NULL);

            // Do the math to determine how long the match was paused
            double timePaused = difftime(now, MATCH_PAUSED);

            // Create a temporary variable to store and manipulate the match start time
            struct tm modMatchStart = *localtime(&MATCH_START);

            // Manipulate the time by adding the amount of seconds the match was paused in order to be able to accurately
            // calculate the amount of time remaining with LeagueOverseer::getMatchTime()
            modMatchStart.tm_sec += timePaused;

            // Save the manipulated match start time
            MATCH_START = mktime(&modMatchStart);
            logMessage(pluginSettings.getVerboseLevel(), "debug", "Match paused for %.f seconds. Match continuing at %s.", timePaused, getMatchTime().c_str());

            PauseResumeMatchEvent resumeEvent = PauseResumeMatchEvent();

            resumeEvent.setState(false)
                       .setTime(getMatchTime())
                       .setBZID(getPlayerBZID(gameResumeData->playerID))
                       .save();

            currentMatch.saveEvent(resumeEvent.getJsonObject());

            logMessage(pluginSettings.getVerboseLevel(), "debug", "PauseResumeMatchEvent JSON -> %s", resumeEvent.toString());
        }
        break;

        case bz_eGameStartEvent: // This event is triggered when a timed game begins
        {
            logMessage(pluginSettings.getVerboseLevel(), "debug", "A match has started");

            // Empty our list of players since we don't need a history
            activePlayerList.clear();

            // We started recording a match, so save the status
            RECORDING = bz_startRecBuf();

            // We want to notify the logs if we couldn't start recording just in case an issue were to occur and the server
            // owner needs to check to see if players were lying about there no replay
            if (RECORDING)
            {
                logMessage(pluginSettings.getVerboseLevel(), "debug", "Match recording has started successfully");
            }
            else
            {
                logMessage(0, "error", "This match could not be recorded");
            }

            currentMatch.setMatchDuration((int) bz_getTimeLimit());

            MATCH_START = time(NULL);
        }
        break;

        case bz_eGetAutoTeamEvent: // This event is called for each new player is added to a team
        {
            bz_GetAutoTeamEventData_V1* autoTeamData = (bz_GetAutoTeamEventData_V1*)eventData;

            int playerID = autoTeamData->playerID;
            std::shared_ptr<bz_BasePlayerRecord> playerData(bz_getPlayerByIndex(playerID));

            // Only force new players to observer if a match is in progress
            if (isMatchInProgress())
            {
                // Automatically move non-league members or players who just joined to the observer team
                if (!isLeagueMember(playerID) || !playerAlreadyJoined(playerData->bzID.c_str()))
                {
                    autoTeamData->handled = true;
                    autoTeamData->team    = eObservers;
                }
            }
        }
        break;

        case bz_eGetPlayerMotto: // This event is called when the player joins. It gives us the motto of the player
        {
            bz_GetPlayerMottoData_V2* mottoData = (bz_GetPlayerMottoData_V2*)eventData;

            if (pluginSettings.isMottoFetchEnabled())
            {
                std::map<std::string, std::string> parameters;

                parameters["{motto}"] = mottoData->motto;
                parameters["{team}"]  = getPlayerTeamNameByBZID(mottoData->record->bzID.c_str());

                mottoData->motto = formatMotto(parameters);
            }
        }
        break;

        case bz_ePlayerDieEvent: // This event is called each time a tank is killed
        {
            bz_PlayerDieEventData_V1* dieData = (bz_PlayerDieEventData_V1*)eventData;
            std::shared_ptr<bz_BasePlayerRecord> victimData(bz_getPlayerByIndex(dieData->playerID));
            std::shared_ptr<bz_BasePlayerRecord> killerData(bz_getPlayerByIndex(dieData->killerID));

            if (isMatchInProgress())
            {
                KillMatchEvent killEvent = KillMatchEvent();

                killEvent.setKiller(killerData->bzID.c_str())
                         .setVictim(victimData->bzID.c_str())
                         .setTime(getMatchTime())
                         .save();

                currentMatch.saveEvent(killEvent.getJsonObject());

                logMessage(pluginSettings.getVerboseLevel(), "debug", "KillMatchEvent JSON -> %s", killEvent.toString());
            }
        }
        break;

        case bz_ePlayerJoinEvent: // This event is called each time a player joins the game
        {
            bz_PlayerJoinPartEventData_V1* joinData = (bz_PlayerJoinPartEventData_V1*)eventData;

            int playerID = joinData->playerID;
            std::shared_ptr<bz_BasePlayerRecord> playerData(bz_getPlayerByIndex(playerID));

            setLeagueMember(playerID);
            storePlayerInfo(playerID, playerData->bzID.c_str());

            JoinMatchEvent joinEvent = JoinMatchEvent().setCallsign(playerData->callsign.c_str())
                                                       .setVerified(playerData->verified)
                                                       .setIpAddress(playerData->ipAddress.c_str())
                                                       .setBZID(playerData->bzID.c_str());
            joinEvent.save();

            // Only notify a player if they exist, have joined the observer team, and there is a match in progress
            if (isMatchInProgress() && isValidPlayerID(joinData->playerID) && playerData->team == eObservers)
            {
                bz_sendTextMessagef(BZ_SERVER, joinData->playerID, "*** There is currently %s match in progress, please be respectful. ***",
                                    ((isOfficialMatch()) ? "an official" : "a fun"));
            }

            if (pluginSettings.isMottoFetchEnabled())
            {
                // Only send a URL job if the user is verified
                if (playerData->verified)
                {
                    requestTeamName(playerData->callsign.c_str(), playerData->bzID.c_str());
                }
            }
        }
        break;

        case bz_ePlayerPartEvent: // This event is called each time a player leaves a game
        {
            bz_PlayerJoinPartEventData_V1* partData = (bz_PlayerJoinPartEventData_V1*)eventData;

            int playerID = partData->playerID;
            std::shared_ptr<bz_BasePlayerRecord> playerData(bz_getPlayerByIndex(playerID));

            removePlayerInfo(partData->record->bzID.c_str());

            // Only keep track of the parting player if they are a league member and there is a match in progress
            if (isLeagueMember(playerID) && isMatchInProgress())
            {
                if (!playerAlreadyJoined(playerData->bzID.c_str()))
                {
                    // Create a record for the player who just left
                    Player partingPlayer(playerData->bzID.c_str(), playerData->team, bz_getCurrentTime());

                    // Push the record to our vector
                    activePlayerList.push_back(partingPlayer);
                }
            }
        }
        break;

        case bz_eRawChatMessageEvent: // This event is called for each chat message the server receives. It is called before any filtering is done.
        {
            bz_ChatEventData_V1* chatData  = (bz_ChatEventData_V1*)eventData;

            bz_eTeamType target    = chatData->team;
            int          playerID  = chatData->from,
                         recipient = chatData->to;

            // The server is always allowed to talk
            if (playerID == BZ_SERVER)
            {
                break;
            }

            // A non-league player is attempting to talk
            if (!isLeagueMember(playerID))
            {
                std::string allowedChatTarget = pluginSettings.getAllowedTargetChat(getCurrentGameMode());
                bool ignoreMessage = true;

                if (allowedChatTarget == "Observers")
                {
                    if (recipient == eObservers || bz_getPlayerTeam(recipient) == eObservers)
                    {
                        ignoreMessage = false;
                    }
                }
                else if (allowedChatTarget == "ObvserverAdmins")
                {
                    if (bz_getPlayerTeam(recipient) == eObservers && isVisibleAdmin(recipient))
                    {
                        ignoreMessage = false;
                    }
                }
                else if (allowedChatTarget == "Admins")
                {
                    if (target == eAdministrators || isVisibleAdmin(recipient))
                    {
                        ignoreMessage = false;
                    }
                }
                else if (allowedChatTarget == "All")
                {
                    ignoreMessage = false;
                }

                if (ignoreMessage)
                {
                    chatData->message = "";
                    sendPluginMessage(playerID, pluginSettings.getGuestMessagingMessage(getCurrentGameMode()));
                }
            }
        }
        break;

        case bz_eTickEvent: // This event is called once for each BZFS main loop
        {
            // Get the total number of tanks playing
            int totalTanks = bz_getTeamCount(eRedTeam) + bz_getTeamCount(eGreenTeam) + bz_getTeamCount(eBlueTeam) + bz_getTeamCount(ePurpleTeam);

            // If there are no tanks playing, then we need to do some clean up
            if (totalTanks == 0)
            {
                // If there is an official match and no tanks playing, we need to cancel it
                if (isOfficialMatch())
                {
                    currentMatch.cancelMatch("Official match automatically canceled due to all players leaving the match.");
                }

                // If we have players recorded and there's no one around, empty the list
                if (!activePlayerList.empty())
                {
                    activePlayerList.clear();
                }

                // If there is a countdown active an no tanks are playing, then cancel it
                if (bz_isCountDownActive())
                {
                    bz_gameOver(253, eObservers);
                    logMessage(pluginSettings.getVerboseLevel(), "debug", "Game ended because no players were found playing with an active countdown.");
                }
            }

            // Let's get the roll call only if there is an official match
            if (isOfficialMatch())
            {
                // Check if the start time is not negative since our default value for the approxTimeProgress is -1. Also check
                // if it's time to do a roll call, which is defined as 90 seconds after the start of the match by default,
                // and make sure we don't have any match participants recorded and the match isn't paused
                if (getMatchProgress() > currentMatch.getMatchRollCall() && currentMatch.isRosterEmpty() &&
                    !bz_isCountDownPaused() && !bz_isCountDownInProgress())
                {
                    logMessage(pluginSettings.getVerboseLevel(), "debug", "Processing roll call...");

                    // @TODO Make sure all of these variables are used
                    std::shared_ptr<bz_APIIntList> playerList(bz_getPlayerIndexList());
                    bool invalidateRollCall, teamOneError, teamTwoError;
                    std::string teamOneMotto, teamTwoMotto;
                    int teamOneID, teamTwoID;

                    invalidateRollCall = teamOneError = teamTwoError = false;
                    teamOneMotto = teamTwoMotto = "";

                    // We can't do a roll call if the player list wasn't created
                    if (!playerList)
                    {
                        logMessage(pluginSettings.getVerboseLevel(), "error", "Failure to create player list for roll call.");
                        return;
                    }

                    for (unsigned int i = 0; i < playerList->size(); i++)
                    {
                        bz_BasePlayerRecord* playerRecord = bz_getPlayerByIndex(playerList->get(i));

                        if (playerRecord && isLeagueMember(playerRecord->playerID) && bz_getPlayerTeam(playerList->get(i)) != eObservers) // If player is not an observer
                        {
                            currentMatch.savePlayer(playerRecord, getTeamIdFromBZID(playerRecord->bzID.c_str()));

                            // @TODO Rewrite this function to be updated
                            // Check if there is any need to invalidate a roll call from a team
                            //validateTeamName(invalidateRollCall, teamOneError, currentPlayer, teamOneMotto, TEAM_ONE);
                            //validateTeamName(invalidateRollCall, teamTwoError, currentPlayer, teamTwoMotto, TEAM_TWO);
                        }

                        bz_freePlayerRecord(playerRecord);
                    }

                    // We were asked to invalidate the roll call because of some issue so let's check if there is still time for
                    // another roll call
                    if (invalidateRollCall && currentMatch.incrementMatchRollCall(60) < currentMatch.getMatchDuration())
                    {
                        logMessage(pluginSettings.getDebugLevel(), "debug", "Invalid player found on field at %s.", getMatchTime().c_str());

                        // There was an error with one of the members of either team, so request a team name update for all of
                        // the team members to try to fix any inconsistencies of different team names
                        //if (teamOneError) { requestTeamName(TEAM_ONE); }
                        //if (teamTwoError) { requestTeamName(TEAM_TWO); }

                        // Delay the next roll call by 60 seconds
                        logMessage(pluginSettings.getVerboseLevel(), "debug", "Match roll call time has been delayed by 60 seconds.");

                        // Clear the struct because it's useless data
                        currentMatch.clearPlayerRoster();
                        logMessage(pluginSettings.getVerboseLevel(), "debug", "Match participants have been cleared.");
                    }

                    // There is no need to invalidate the roll call so the team names must be right so save them in the struct
                    if (!invalidateRollCall)
                    {
                        currentMatch.setTeamOneID(teamOneID).setTeamOneName(teamOneMotto)
                                    .setTeamTwoID(teamTwoID).setTeamTwoName(teamTwoMotto);

                        logMessage(pluginSettings.getVerboseLevel(), "debug", "Team One set to: %s", currentMatch.getTeamOneName().c_str());
                        logMessage(pluginSettings.getVerboseLevel(), "debug", "Team Two set to: %s", currentMatch.getTeamTwoName().c_str());
                    }
                }
            }
        }
        break;

        default: break;
    }
}