void ResetZeroTeams() { if (bz_getTeamCount(eRedTeam) == 0) { tctf.redLastTime = bz_getCurrentTime (); tctf.redLastWarn = bz_getCurrentTime (); } if (bz_getTeamCount(eGreenTeam) == 0) { tctf.greenLastTime = bz_getCurrentTime (); tctf.greenLastWarn = bz_getCurrentTime (); } if (bz_getTeamCount(eBlueTeam) == 0) { tctf.blueLastTime = bz_getCurrentTime (); tctf.blueLastWarn = bz_getCurrentTime (); } if (bz_getTeamCount(ePurpleTeam) == 0) { tctf.purpleLastTime = bz_getCurrentTime (); tctf.purpleLastWarn = bz_getCurrentTime (); } return; }
bool fairCTF::isEven(bz_eTeamType teamLeaving) { int teamsizes[4]; teamsizes[0] = bz_getTeamCount (eRedTeam); teamsizes[1] = bz_getTeamCount (eGreenTeam); teamsizes[2] = bz_getTeamCount (eBlueTeam); teamsizes[3] = bz_getTeamCount (ePurpleTeam); int leavingTeamIndex = (int)teamLeaving; if (leavingTeamIndex >= 1 && leavingTeamIndex <= 4) { // Decrement the team count for the player that's leaving the game. teamsizes[leavingTeamIndex - 1]--; } //check fairness int smallestTeam = 10000; //impossibly high int largestTeam = 0; for (int x = 0; x < 4; x++) { if (teamsizes[x] > largestTeam) { largestTeam = teamsizes[x]; } if (teamsizes[x] != 0 && teamsizes[x] < smallestTeam) { smallestTeam = teamsizes[x]; } } //check differences and ratios if (smallestTeam == 10000 || largestTeam == smallestTeam) //equal, or server has no team tanks { return true; } if (smallestTeam <= max_gap_by_1) // user-defined cap on a difference of 1 { return false; } if (largestTeam - smallestTeam == 1) //after UD limit { return true; } if ((static_cast<float> (largestTeam - smallestTeam)) / smallestTeam > max_ratio) //greater than specified gap { return false; } if (largestTeam - smallestTeam >= max_gap) { return false; } return true; }
void leagueOverSeer::updateTeamNames(void) { int totaltanks = bz_getTeamCount(eRogueTeam) + bz_getTeamCount(eRedTeam) + bz_getTeamCount(eGreenTeam) + bz_getTeamCount(eBlueTeam) + bz_getTeamCount(ePurpleTeam) + bz_getTeamCount(eObservers); if (totaltanks > 0) return; // Build the POST data for the URL job std::string teamNameDump = "query=teamDump"; bz_debugMessagef(DEBUG, "DEBUG :: League Over Seer :: Updating Team name database..."); bz_addURLJob(LEAGUE_URL.c_str(), this, teamNameDump.c_str()); //Send the team update request to the league website }
void killAllHunters(std::string messagepass) { bz_APIIntList *playerList = bz_newIntList(); bz_getPlayerIndexList(playerList); for (unsigned int i = 0; i < playerList->size(); i++){ bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerList->operator[](i)); if (player) { if (player->team != eRabbitTeam) { bz_killPlayer(player->playerID, true, BZ_SERVER); bz_sendTextMessage(BZ_SERVER, player->playerID, messagepass.c_str()); if (rrzoneinfo.soundEnabled) bz_sendPlayCustomLocalSound(player->playerID,"flag_lost"); } if (player->team == eRabbitTeam && rrzoneinfo.soundEnabled && bz_getTeamCount(eHunterTeam) > 0) bz_sendPlayCustomLocalSound(player->playerID,"flag_won"); bz_freePlayerRecord(player); } } bz_deleteIntList(playerList); return; }
bool OnlyOneTeamPlaying() { int R = bz_getTeamCount(eRedTeam); int G = bz_getTeamCount(eGreenTeam); int B = bz_getTeamCount(eBlueTeam); int P = bz_getTeamCount(ePurpleTeam); if (R == 0 && G == 0 && B == 0 && P > 0) return true; if (R == 0 && G == 0 && P == 0 && B > 0) return true; if (R == 0 && B == 0 && P == 0 && G > 0) return true; if (G == 0 && B == 0 && P == 0 && R > 0) return true; return false; }
void autoTime() { int numPlayers = bz_getTeamCount(eRedTeam) + bz_getTeamCount(eGreenTeam) + bz_getTeamCount(eBlueTeam) + bz_getTeamCount(ePurpleTeam) + bz_getTeamCount(eRogueTeam); if (!keepaway.autoTimeOn || numPlayers < 3) { keepaway.adjustedTime = keepaway.TTH; return; } double timeDown = ( 1 - ((double)numPlayers - 2) * keepaway.timeMult); if (timeDown < keepaway.timeMultMin) timeDown = keepaway.timeMultMin; keepaway.adjustedTime = (int)(keepaway.TTH * timeDown); return; }
bool onePlayer() { int numPlayers = bz_getTeamCount(eRedTeam) + bz_getTeamCount(eGreenTeam) + bz_getTeamCount(eBlueTeam) + bz_getTeamCount(ePurpleTeam) + bz_getTeamCount(eRogueTeam); if (numPlayers <= 1) { if (!koth.onePlayerWarn) bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, "King of the Hill disabled: less than 2 players."); koth.onePlayerWarn = true; return true; } else { if (koth.onePlayerWarn) bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, "King of the Hill enabled: more than 1 player."); koth.onePlayerWarn = false; return false; } }
inline bool oneTeam(bz_eTeamType leavingPlayerTeam) { int RT = bz_getTeamCount(eRedTeam); int GT = bz_getTeamCount(eGreenTeam); int BT = bz_getTeamCount(eBlueTeam); int PT = bz_getTeamCount(ePurpleTeam); int RGT = bz_getTeamCount(eRogueTeam); if (leavingPlayerTeam == eRedTeam) RT--; if (leavingPlayerTeam == eGreenTeam) GT--; if (leavingPlayerTeam == eBlueTeam) BT--; if (leavingPlayerTeam == ePurpleTeam) PT--; if (leavingPlayerTeam == eRogueTeam) RGT--; int Test1 = (RT * GT) + (RT * BT) + (RT * PT) + (GT * BT) + (GT * PT) + (BT * PT); int Test2 = RT + GT + BT + PT + RGT; if (Test1 < 1 && Test2 < 2) { if (!keepaway.oneTeamWarn) bz_sendTextMessage (BZ_SERVER, BZ_ALLUSERS, "Keep Away disabled: less than 2 teams."); keepaway.oneTeamWarn = true; return true; } else { if (keepaway.oneTeamWarn) bz_sendTextMessage (BZ_SERVER, BZ_ALLUSERS, "Keep Away enabled: more than 1 team."); keepaway.oneTeamWarn = false; return false; } }
int TeamCheck(bz_eTeamType Team, const char* Color, double LastWarn, double LastTime) { if (bz_getTeamCount(Team) != 0 && tctf.timerRunning) { tctf.timeElapsed = bz_getCurrentTime() - LastTime; tctf.timeRemaining = tctf.timeLimit - tctf.timeElapsed; if (bz_getCurrentTime() - LastWarn > 60) { tctf.adjTime = (int)(tctf.timeRemaining / 60); bz_sendTextMessagef (BZ_SERVER, Team, "%s Team: less than %i minute(s) left to capture a flag!", Color, tctf.adjTime + 1); return 1; // 1 = reset team's LastWarn } if (bz_getCurrentTime() - LastWarn > 30 && tctf.timeRemaining < 30) { bz_sendTextMessagef (BZ_SERVER, Team, "%s Team: less than 30 seconds left to capture a flag!", Color); return 1; // 1 = reset team's LastWarn } if (bz_getCurrentTime() - LastWarn > 10 && tctf.timeRemaining < 20 && tctf.timeRemaining > 10) { bz_sendTextMessagef (BZ_SERVER, Team, "%s Team: less than 20 seconds left to capture a flag!", Color); return 1; // 1 = reset team's LastWarn } if (bz_getCurrentTime() - LastWarn > 10 && tctf.timeRemaining < 10 && tctf.timeRemaining > 1) { bz_sendTextMessagef (BZ_SERVER, Team, "%s Team: less than 10 seconds left to capture a flag!", Color); return 1; // 1 = reset team's LastWarn } if (tctf.timeElapsed >= tctf.timeLimit) { KillTeam(Team); bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "%s team did not capture any other team flags in time.", Color); tctf.adjTime = (int)(tctf.timeLimit / 60 + 0.5); bz_sendTextMessagef (BZ_SERVER, Team, "CTF timer is reset to %i minutes for the %s team.", tctf.adjTime, Color); return 2; // 2 = reset team's LastWarn and LastTime } } return 0; // 0 = no need to reset teams LastWarn or LastTime }
void rabbitTimer::Event(bz_EventData *eventData) { if (eventData->eventType == bz_eTickEvent) { bz_TickEventData_V1* tickdata = (bz_TickEventData_V1*)eventData; if (currentRabbit != -1 && tickdata->eventTime >= rabbitDeathTime) { //kill the wabbit! bz_killPlayer(currentRabbit, false, BZ_SERVER); //stopgap. the kill event should do this, really... currentRabbit = -1; rabbitDeathTime = (float)tickdata->eventTime + rabbitKillTimeLimit; bz_sendTextMessage (BZ_SERVER, BZ_ALLUSERS, "Time's up! Selecting new rabbit."); } else if (currentRabbit == -1 && bz_getTeamCount(eHunterTeam) >= 3) //make sure we've got enough people before reactivating the timer { //find the new rabbit bz_APIIntList pl; bz_getPlayerIndexList(&pl); for (unsigned int i = 0; i < pl.size() && currentRabbit == -1; i++) { bz_BasePlayerRecord* pr = bz_getPlayerByIndex(pl.get(i)); if (pr != NULL) { if (pr->team == eRabbitTeam) { currentRabbit = pr->playerID; int limit = (int)rabbitKillTimeLimit; bz_sendTextMessage(BZ_SERVER, currentRabbit, bz_format("You have %d seconds to make a kill!", limit)); } bz_freePlayerRecord(pr); } } } } else if (eventData->eventType == bz_ePlayerDieEvent) { bz_PlayerDieEventData_V1* killdata = (bz_PlayerDieEventData_V1*)eventData; if (killdata->team == eRabbitTeam) { currentRabbit = -1; //we will sort this out on the next tick rabbitDeathTime = (float)killdata->eventTime + rabbitKillTimeLimit; } else if (killdata->killerTeam == eRabbitTeam && currentRabbit != -1) { if (rollOver) { rabbitDeathTime += rabbitKillTimeLimit; int limit = (int)rabbitKillTimeLimit; int timeremaining = (int)(rabbitDeathTime - killdata->eventTime); bz_sendTextMessage(BZ_SERVER, currentRabbit, bz_format("+%d seconds: %d seconds remaining.", limit, timeremaining)); } else { rabbitDeathTime = (float)killdata->eventTime + rabbitKillTimeLimit; int limit = (int)rabbitKillTimeLimit; bz_sendTextMessage(BZ_SERVER, currentRabbit, bz_format("%d seconds remaining.", limit)); } } } else if (eventData->eventType == bz_ePlayerDieEvent) { bz_PlayerJoinPartEventData_V1* partdata = (bz_PlayerJoinPartEventData_V1*)eventData; if (partdata->record->team == eRabbitTeam) //we need to select a new rabbit if the rabbit leaves. { currentRabbit = -1; //we will sort this out on the next tick rabbitDeathTime = (float)partdata->eventTime + rabbitKillTimeLimit; } } }
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; } }
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; }
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; } }
bool TeamsBalanced() { // if not enough team players - no need to check any further: if (bz_getTeamCount(eRedTeam) + bz_getTeamCount(eGreenTeam) + bz_getTeamCount(eBlueTeam) + bz_getTeamCount( ePurpleTeam) <= 1) return false; // check for fair ctf - only need 2 teams close (TeamRatioTolerance or better) // this is crude - can be done better I'm sure: float TeamRatioTolerance = 0.75; // if not same size, at least 3 versus 4 or better float RatioRG = 0; float RatioRB = 0; float RatioRP = 0; float RatioGB = 0; float RatioBP = 0; float RatioGP = 0; float RS = (float)bz_getTeamCount(eRedTeam); // "GS" is a macro defined in /usr/include/sys/regset.h on Solaris x86 float _GS = (float)bz_getTeamCount(eGreenTeam); float BS = (float)bz_getTeamCount(eBlueTeam); float PS = (float)bz_getTeamCount(ePurpleTeam); if (RS >= _GS && RS !=0) RatioRG = (_GS / RS); if (_GS > RS && _GS !=0) RatioRG = (RS / _GS); if (RS >= BS && RS !=0) RatioRB = (BS / RS); if (BS > RS && BS !=0) RatioRB = (RS / BS); if (RS >= PS && RS !=0) RatioRP = (PS / RS); if (PS > RS && PS !=0) RatioRP = (RS / PS); if (_GS >= BS && _GS !=0) RatioGB = (BS / _GS); if (BS > _GS && BS !=0) RatioGB = (_GS / BS); if (PS >= _GS && PS !=0) RatioGP = (_GS / PS); if (_GS > PS && _GS !=0) RatioGP = (PS / _GS); if (BS >= PS && BS !=0) RatioBP = (PS / BS); if (PS > BS && PS !=0) RatioBP = (BS / PS); if (RatioRG >= TeamRatioTolerance || RatioRB >= TeamRatioTolerance || RatioRP >= TeamRatioTolerance || RatioGB >= TeamRatioTolerance || RatioGP >= TeamRatioTolerance || RatioBP >= TeamRatioTolerance) return true; else return false; }
bool TeamsBalanced() { // if not enough team players - no need to check any further: if (bz_getTeamCount(eRedTeam) + bz_getTeamCount(eGreenTeam) + bz_getTeamCount(eBlueTeam) + bz_getTeamCount(ePurpleTeam) <= 1) return false; // check for fair ctf - only need 2 teams close (TeamRatioTolerance or better) // this is crude - can be done better I'm sure: float TeamRatioTolerance = 0.75; // if not same size, at least 3 versus 4 or better float RatioRG = 0; float RatioRB = 0; float RatioRP = 0; float RatioGB = 0; float RatioBP = 0; float RatioGP = 0; float RS = (float) bz_getTeamCount(eRedTeam); float GS = (float) bz_getTeamCount(eGreenTeam); float BS = (float) bz_getTeamCount(eBlueTeam); float PS = (float) bz_getTeamCount(ePurpleTeam); if (RS >= GS && RS != 0) RatioRG = (GS / RS); if (GS > RS && GS != 0) RatioRG = (RS / GS); if (RS >= BS && RS != 0) RatioRB = (BS / RS); if (BS > RS && BS != 0) RatioRB = (RS / BS); if (RS >= PS && RS != 0) RatioRP = (PS / RS); if (PS > RS && PS != 0) RatioRP = (RS / PS); if (GS >= BS && GS != 0) RatioGB = (BS / GS); if (BS > GS && BS != 0) RatioGB = (GS / BS); if (PS >= GS && PS != 0) RatioGP = (GS / PS); if (GS > PS && GS != 0) RatioGP = (PS / GS); if (BS >= PS && BS != 0) RatioBP = (PS / BS); if (PS > BS && PS != 0) RatioBP = (BS / PS); if (RatioRG >= TeamRatioTolerance || RatioRB >= TeamRatioTolerance || RatioRP >= TeamRatioTolerance || RatioGB >= TeamRatioTolerance || RatioGP >= TeamRatioTolerance || RatioBP >= TeamRatioTolerance) { return true; } else { return false; } }
void TeamFlagResetHandler::Event ( bz_EventData *eventData ) { if (eventData->eventType != bz_eTickEvent) return; if (tfr.timerOff == true) return; bz_APIIntList *playerList = bz_newIntList(); bz_getPlayerIndexList ( playerList ); // check to see if anyone has picked up a team flag & count players per team for ( unsigned int i = 0; i < playerList->size(); i++ ){ bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerList->operator[](i)); if (player) { tfr.flagTouched = bz_getPlayerFlag(player->playerID); if (tfr.flagTouched){ if (strcmp(tfr.flagTouched, "R*") == 0){ tfr.redLastTouched = bz_getCurrentTime(); tfr.redFlagWasHeld = true; } if (strcmp(tfr.flagTouched, "G*") == 0){ tfr.greenLastTouched = bz_getCurrentTime(); tfr.greenFlagWasHeld = true; } if (strcmp(tfr.flagTouched, "B*") == 0){ tfr.blueLastTouched = bz_getCurrentTime(); tfr.blueFlagWasHeld = true; } if (strcmp(tfr.flagTouched, "P*") == 0){ tfr.purpleLastTouched = bz_getCurrentTime(); tfr.purpleFlagWasHeld = true; } } bz_freePlayerRecord(player); } } bz_deleteIntList(playerList); // if no teamplay, no need to reset flags tfr.OKToReset = false; if (bz_getTeamCount(eRedTeam) * bz_getTeamCount(eGreenTeam) > 0) tfr.OKToReset = true; if (bz_getTeamCount(eRedTeam) * bz_getTeamCount(eBlueTeam) > 0) tfr.OKToReset = true; if (bz_getTeamCount(eRedTeam) * bz_getTeamCount(ePurpleTeam) > 0) tfr.OKToReset = true; if (bz_getTeamCount(eGreenTeam) * bz_getTeamCount(eBlueTeam) > 0) tfr.OKToReset = true; if (bz_getTeamCount(eGreenTeam) * bz_getTeamCount(ePurpleTeam) > 0) tfr.OKToReset = true; if (bz_getTeamCount(eBlueTeam) * bz_getTeamCount(ePurpleTeam) > 0) tfr.OKToReset = true; if (tfr.OKToReset == false){ ResetFlagData(); return; } // check if time's up on flags and reset (if they were held at least once after last reset) if (bz_getCurrentTime() - tfr.redLastTouched > tfr.idleTime && tfr.redFlagWasHeld){ if (bz_getTeamCount(eRedTeam) > 0){ resetTeamFlag ("R*"); bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "Red flag sat idle too long - reset by server."); } tfr.redFlagWasHeld = false; tfr.redLastTouched = bz_getCurrentTime(); } if (bz_getCurrentTime() - tfr.greenLastTouched > tfr.idleTime && tfr.greenFlagWasHeld){ if (bz_getTeamCount(eGreenTeam) > 0){ resetTeamFlag ("G*"); bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "Green flag sat idle too long - reset by server."); } tfr.greenLastTouched = bz_getCurrentTime(); tfr.greenFlagWasHeld = false; } if (bz_getCurrentTime() - tfr.blueLastTouched > tfr.idleTime && tfr.blueFlagWasHeld){ if (bz_getTeamCount(eBlueTeam) > 0){ resetTeamFlag ("B*"); bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "Blue flag sat idle too long - reset by server."); } tfr.blueLastTouched = bz_getCurrentTime(); tfr.blueFlagWasHeld = false; } if (bz_getCurrentTime() - tfr.purpleLastTouched > tfr.idleTime && tfr.purpleFlagWasHeld){ if (bz_getTeamCount(ePurpleTeam) > 0){ resetTeamFlag ("P*"); bz_sendTextMessagef (BZ_SERVER, BZ_ALLUSERS, "Purple flag sat idle too long - reset by server."); } tfr.purpleLastTouched = bz_getCurrentTime(); tfr.purpleFlagWasHeld = false; } return; }
void RabidRabbitEventHandler::Event(bz_EventData *eventData) { if (eventData->eventType == bz_ePlayerDieEvent) { bz_PlayerDieEventData_V1 *DieData = (bz_PlayerDieEventData_V1*)eventData; if (rrzoneinfo.cycleOnDie && DieData->team == eRabbitTeam) { unsigned int i = rrzoneinfo.currentKillZone; if (i == (zoneList.size() - 1)) rrzoneinfo.currentKillZone = 0; else rrzoneinfo.currentKillZone++; } return; } if ((eventData->eventType != bz_eTickEvent) || (zoneList.size() < 2)) return; for (unsigned int i = 0; i < zoneList.size(); i++) { if (!zoneList[i].WWFired && rrzoneinfo.currentKillZone == i) { bz_fireWorldWep(zoneList[i].WW.c_str(), zoneList[i].WWLifetime, BZ_SERVER,zoneList[i].WWPosition, zoneList[i].WWTilt, zoneList[i].WWDirection, zoneList[i].WWShotID, zoneList[i].WWDT); zoneList[i].WWFired = true; zoneList[i].WWLastFired = bz_getCurrentTime(); } else { if ((bz_getCurrentTime() - zoneList[i].WWLastFired) > zoneList[i].WWRepeat) zoneList[i].WWFired = false; } } bz_APIIntList *playerList = bz_newIntList(); bz_getPlayerIndexList(playerList); for (unsigned int h = 0; h < playerList->size(); h++) { bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerList->operator[](h)); if (player) { for (unsigned int i = 0; i < zoneList.size(); i++) { if (zoneList[i].pointIn(player->lastKnownState.pos) && player->spawned && player->team == eRabbitTeam && rrzoneinfo.currentKillZone != i && !rrzoneinfo.rabbitNotifiedWrongZone) { bz_sendTextMessage(BZ_SERVER,player->playerID, "You are not in the current Rabid Rabbit zone - try another."); rrzoneinfo.rabbitNotifiedWrongZone = true; rrzoneinfo.rabbitNotifiedWrongZoneNum = i; } if (!zoneList[i].pointIn(player->lastKnownState.pos) && player->spawned && player->team == eRabbitTeam && rrzoneinfo.rabbitNotifiedWrongZone && rrzoneinfo.rabbitNotifiedWrongZoneNum == i) rrzoneinfo.rabbitNotifiedWrongZone = false; if (zoneList[i].pointIn(player->lastKnownState.pos) && player->spawned && player->team == eRabbitTeam && rrzoneinfo.currentKillZone == i && bz_getTeamCount(eHunterTeam) > 0) { killAllHunters(zoneList[i].servermessage); rrzoneinfo.rabbitNotifiedWrongZone = true; rrzoneinfo.rabbitNotifiedWrongZoneNum = i; if (i == (zoneList.size() - 1)) rrzoneinfo.currentKillZone = 0; else rrzoneinfo.currentKillZone++; rrzoneinfo.rabbitNotifiedWrongZone = true; rrzoneinfo.rabbitNotifiedWrongZoneNum = i; } if (zoneList[i].pointIn(player->lastKnownState.pos) && player->spawned && player->team != eRabbitTeam && zoneList[i].zonekillhunter) { bz_killPlayer(player->playerID, true, BZ_SERVER); bz_sendTextMessage (BZ_SERVER, player->playerID, zoneList[i].playermessage.c_str()); } } bz_freePlayerRecord(player); } } bz_deleteIntList(playerList); return; }